具有分层对象的 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
现在我的问题:
- 相应的视图模型会是什么样子?是否有集合的参考实现? 模型
- 或视图模型或两者应实现
INotifyPropertyChanged
,INotifyCollectionChanged
还是子列表应为ObservableCollection<MyModel>
类型?如果是这样,何时致电OnPropertyChanged()
?
现在进行显示:
我想在 TreeView 中显示对象的名称,但在选择元素时,我希望收到该事件的通知(并获取相应的元素)。视图模型必须以某种方式支持这一点。类似于持有我可以在 XAML 中绑定到的列表(比如 MyModelList
),例如:
<TreeView ...
ItemsSource="{Binding ElementName=MyModelList, Path=SelectedItem.Name}"
... >
以及我可以在哪里使用InputBindings
或EventTriggers
.
尝试使用分层数据模板在树视图中显示树结构
<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");
}
}