具有分层对象的MVVM的参考实现

时间:2014-04-01 08:58:47

标签: c# wpf xaml mvvm treeview

我阅读了几个MVVM教程(1234),但我无法找到问题的正确答案。

我的模型是这样的分层树:

public class MyModel {
    public string Name { get; set; }
    public Guid Id { get; set; }
    public List<MyModel> Children { get; set; }
}

现在我想在这样的TreeView中显示它(如果来自MyModel类型的每个条目):

Root
|-SubElement
|-SubElement2
|  |-SubSubElement1
|-SubElement3

现在我的问题:

  • 相应的View-Model会是什么样子?是否有集合的参考实现?
  • 模型或视图模型或两者是否应实现INotifyPropertyChangedINotifyCollectionChanged或者儿童列表是否属于ObservableCollection<MyModel>类型?如果是,何时致电OnPropertyChanged()

现在显示:

我想在TreeView中显示对象的名称,但是在选择元素时,我希望收到该事件的通知(并获取相应的元素)。 ViewModel必须以某种方式支持这一点。类似于持有我可以在XAML中绑定的列表(例如MyModelList),例如:

<TreeView ...
   ItemsSource="{Binding ElementName=MyModelList, Path=SelectedItem.Name}"

... >

我可以使用InputBindingsEventTriggers

2 个答案:

答案 0 :(得分:3)

尝试使用分层数据模板在TreeView中显示树结构

<Grid>
    <Grid.Resources>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}" 
                                  DataType="{x:Type local:MyModel}">
            <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
    </Grid .Resources>
    <TreeView ItemsSource="{Binding MyModelList}"/>
</Grid>

通过此MSDN博客以更好地理解 - TreeView and HierarchicalDataTemplate, Step-by-Step

答案 1 :(得分:1)

  

How would the corresponding View-Model look like?

在这种情况下,Model和集合将在ViewModel中。


  

Should the Model or the View-Model or both implement INotifyPropertyChanged

我建议您使用ObservableCollection<T>,因为Collection中的所有更改都会自动(添加,删除等)出现在其中。将在Model中的属性必须实现INotifyPropertyChanged接口。我个人在Model方面这样做,但是有这个想法的反对者,所以在哪里实施它 - 你个人的愿望。

这个想法的例子:

<强> Model

public class MyModel : NotificationObject // he implement INotifyPropertyChanged 
{
   ...
}

<强> ViewModel

public ObservableCollection<MyModel> MyObjects 
{
    get;
    set;
}

// in Constructor of ViewModel
MyLogObjects = new ObservableCollection<MyModel>();

  

When selecting the element, I want to be notified of that event

在WPF和Silverlight中TreeView.SelectedItem是一个只读属性。在这种情况下,您可以看到this示例:

<StackPanel x:Name="LayoutRoot"> 
    <StackPanel.Resources> 
        <sdk:HierarchicalDataTemplate x:Key="ChildTemplate" ItemsSource="{Binding Path=Children}" > 
            <TextBlock Text="{Binding Path=Name}" /> 
        </sdk:HierarchicalDataTemplate> 

        <sdk:HierarchicalDataTemplate x:Key="NameTemplate" 
                                      ItemsSource="{Binding Path=Children}" 
                                      ItemTemplate="{StaticResource ChildTemplate}">
            <TextBlock Text="{Binding Path=Name}" FontWeight="Bold" /> 
        </sdk:HierarchicalDataTemplate> 
    </StackPanel.Resources> 

    <sdk:TreeView x:Name="myTreeView"
                  Width="400"  
                  Height="300" 
                  ItemsSource="{Binding HierarchicalAreas}" 
                  ItemTemplate="{StaticResource NameTemplate}"
                  local:Attached.TreeViewSelectedItem="{Binding SelectedArea, Mode=TwoWay}" /> 
</StackPanel> 

Silverlight

所需的前缀sdk:

对于通知事件,您可以在构造函数中为PropertyChangedEventHandler创建ViewModel事件处理程序,以便知道 SelectedItem 已更改:

public MyViewModel() 
{
    MyModel = new MyModel();        
    MyModel.PropertyChanged += new PropertyChangedEventHandler(MyModel_PropertyChanged);
}

private void MyModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName.Equals("SelectedItem")) 
    {
        System.Diagnostics.Debug.WriteLine("SelectedItem changed");
    }            
}