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

本文关键字:MVVM 实现 参考 对象 分层 | 更新日期: 2023-09-27 17:55:36

我读了几个MVVM教程(1,2,3,4),但我找不到我的问题的正确答案。

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

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

现在我想在树视图中显示它,如下所示(如果来自 MyModel 类型,则每个条目):

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

现在我的问题:

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

现在进行显示:

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

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

以及我可以在哪里使用InputBindingsEventTriggers.

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

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

<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 博客以更好地了解 - 树视图和分层数据模板,分步

How would the corresponding View-Model look like?

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


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

我建议您使用 ObservableCollection<T> ,因为收藏的所有更改都会自动(添加、删除等)出现在其中。将位于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:

对于通知的事件,您可以在构造函数中为 ViewModel 创建一个 PropertyChangedEventHandler 事件处理程序,以了解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");
    }            
}