我的MVVM构造中有两个级别的对象:
MainWindow
绑定到MainWindowVM
支持的ApplicationModel
ChildView
绑定到ChildVM
支持的ChildModel
分别进行绑定。因此,我在ApplicationModel中创建了ChildModels的集合,然后在MainWindowVM中将其转换为ChildVM的集合,这又用ChildView控件填充了MainWindow中的ItemsControl。
问题是我无法将这些生成的ChildView与生成的ChildVM挂钩。
模型是实现INotifyPropertyChanged的直接对象:
class ApplicationModel : NotifyingObject
{
private ObservableCollection<ChildModel> children = new ObservableCollection<ChildModel>() { new ChildModel(), new ChildModel() };
public ObservableCollection<ChildModel> Children
{
get => children;
}
}
class ChildModel : NotifyingObject
{
private string childText;
public string ChildText
{
get => childText;
set
{
if (childText != value)
{
childText = value;
NotifyPropertyChanged();
}
}
}
}
ViewModels又实现INotifyPropertyChanged并挂接到模型的更改中。缺少许多功能(添加/删除),因为它不需要进行演示:
class MainWindowVM : NotifyingObject
{
private ApplicationModel model = new ApplicationModel();
private ObservableCollection<ChildVM> childVMs = new ObservableCollection<ChildVM>();
public MainWindowVM()
{
model.PropertyChanged += Model_PropertyChanged;
model.Children.ToList().ForEach(c => childVMs.Add(new ChildVM(c)));
}
private void Model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(model.Children))
NotifyPropertyChanged(nameof(ChildrenVMs));
}
public ObservableCollection<ChildVM> ChildrenVMs
{
get => childVMs;
}
}
class ChildVM : NotifyingObject
{
private ChildModel model;
public ChildVM() : this(new ChildModel() { ChildText = "Dummy Content" }) { }
public ChildVM(ChildModel model)
{
this.model = model;
model.PropertyChanged += Model_PropertyChanged;
}
private void Model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
NotifyPropertyChanged(nameof(ChildText));
}
public String ChildText
{
get => model.ChildText;
set => model.ChildText = value;
}
}
现在,ChildView非常贫瘠:
<UserControl x:Class="WpfDemo.ChildView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfDemo"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<local:ChildVM />
</UserControl.DataContext>
<Grid>
<TextBox Text="{Binding Path=ChildText}"></TextBox>
</Grid>
</UserControl>
最后是MainWindow。如您所见,我已经尝试在模板和样式上设置绑定。他们不会单独或一起工作。我也尝试过删除DataContext规范...
<Window x:Class="WpfDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfDemo"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowVM />
</Window.DataContext>
<Grid>
<ItemsControl ItemsSource="{Binding Path=ChildrenVMs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:ChildView DataContext="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="FrameworkElement.DataContext" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
</Window>