从WPF中的视图模型动态地通知视图

时间:2013-09-17 08:54:42

标签: wpf xaml data-binding mvvm user-controls

在我的WPF应用程序中,我必须创建一个对象设计器。这个设计器是许多其他用户控件的ListView(自定义Grid包含costum-stackpanel,其中包含我要显示的自定义对象)。

因此,为了更好地构建我的设计器,我为每个层次级别创建了一个模板,并将其放在View中(作为用户控件)。与此同时,我为每个视图创建了相应的viewModels。

将视图绑定到他们的视图模型,我在App.xaml文件中放入以下代码:

<Application.Resources>
    <DataTemplate DataType="{x:Type ViewModel:DesignerViewModel}">
        <View:Designer />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:FirstLevelViewModel}">
        <View:FirstLevel />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:SecondLevelViewModel}">
        <View:Secondlevel />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:ThirdLevelViewModel}">
        <View:Thirdlevel />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:CircleViewModel}">
        <View:Circle />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:RectangleViewModel}">
        <View:Rectangle />
    </DataTemplate>
</Application.Resources>

它在我第一次加载应用程序时起作用(我认为因为绑定仅在视图的构造函数创建时完成)。但在此之后,View-Models中的每个修改都不会自动通知视图!!!

我找到的唯一解决方案是在任何视图 - 模型修改后重新创建我的设计器视图!!

有没有人有更好的解决方案?因为我认为我的解决方案不是很干净!

注意:我在所有viewModel中实现了INotifyPropertyChanged。

UPDATE&GT;&GT;&GT;&GT;

所以,我举一个例子:

这是我的Designer Xaml:

<Grid>
    <ListView SelectionMode="Single"
    VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
    ItemsSource="{Binding FirstLevelViewModelList}" >

        <ListView.ItemTemplate>
            <DataTemplate>
              <View:FirstLevel HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</Grid>

这是我的DesignerViewModel类:

 public class DesignerViewModel : AViewModel
{
    #region Property

    public int FirstLevelCounter
    {
        get;
        set;
    }

    private List<FirstLevelViewModel> FirstLevelViewModelList;

    public List<FirstLevelViewModel> FirstLevelViewModelList
    {
        get { return FirstLevelViewModelList; }
        set { FirstLevelViewModelList = value; 
OnPropertyChanged("FirstLevelViewModelList"); }
    }

    #region Constructor

    /// <summary>
    /// Constructor
    /// </summary>
    private DesignerViewModel()
    {
        FirstLevelViewModelList = new List<FirstLevelViewModel>();
        FirstLevelCounter = 0;

    }

    private static DesignerViewModel instance = null;
    private static readonly object padlock = new object();

    public static DesignerStringViewModel Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new DesignerViewModel();
                }
                return instance;
            }
        }
    }
 }

这是我的FirstLevel Xaml:

<Grid>
    <ListView SelectionMode="Single"
    VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
    ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding SecondLevelViewModelList}" BorderBrush="Transparent" Background="Transparent" Height="auto">
    </ListView>
</Grid>

最后,这是我的FirstLevelViewModel类:

公共类FirstLevelViewModel:AViewModel     {         #region Property

    private List<SecondLevelViewModel> SecondLevelViewModelList;
    public List<SecondLevelViewModel> SecondLevelViewModelList
    {
        get { return SecondLevelViewModelList; }
        set { SecondLevelViewModelList = value; 
OnPropertyChanged("SecondLevelViewModelList"); }
    }


    #region Constructor


    public FirstLevelViewModel()
    {
        SecondLevelViewModelList = new List<SecondLevelViewModel>();

    }

    #endregion 

}

END-UPDATE&GT;&GT;&GT;&GT;&GT;

2 个答案:

答案 0 :(得分:2)

普通列表没有实现必要的INotifyCollectionChanged,类似于INotifyPropertyChanged告诉WPF和绑定引擎某些内容已发生变化,以便视图可以更新。

您有两种选择:

  1. 使用ObservableCollection代替列表
  2. 创建您自己的集合类型并实现INotifyCollectionChanged

答案 1 :(得分:0)

您的视图模型需要实现INotifyPropertyChanged并在其属性发生更改时引发PropertyChanged事件。