如何将子视图绑定到子视图模型?

时间:2018-07-12 12:57:41

标签: wpf mvvm data-binding

我的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>

0 个答案:

没有答案