绑定到父数据上下文以使用PropertyChangedEventHandler

本文关键字:PropertyChangedEventHandler 上下文 数据 绑定 | 更新日期: 2023-09-27 18:09:52

我在更新列表框时遇到了困难,因为它绑定的列表发生了变化。
主窗口通过代码后置设置了数据上下文:

public partial class MainWindow : Window
{
    private ConfigurationListViewModel _ConfListVM;
    public MainWindow()
    {
        _ConfListVM = new ConfigurationListViewModel();
        InitializeComponent();
        DataContext = _ConfListVM.ConfList;
        this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }
    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        ConfigMng.CreatedConfigurationEvent += new EventHandler(OnCreateConfiguration);
    }
    void OnCreateConfiguration(object sender, EventArgs e)
    {
        _ConfListVM.Add("Test");
    }
}

public class ConfigurationListViewModel
{
    public ConfigurationList ConfList = new ConfigurationList();
}
public class ConfigurationList : INotifyPropertyChanged
{
    private ObservableCollection<Configuration> _ObservableConfList = new ObservableCollection<Configuration>();
    public ObservableCollection<Configuration> ObservableConfList { get { return _ObservableConfList; } set { _ObservableConfList = value; } }
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public ConfigurationList()
    {
        ObservableConfList.Add(new Configuration("aaa"));
        ObservableConfList.Add(new Configuration("bbd"));
    }

    public void Add(Configuration Conf)
    {
        ObservableConfList.Add(Conf);
        OnPropertyChanged(Conf.ConfName);
    }
}

}

在主窗口XAML中我设置了用户控件:

<GroupBox Header="Configurations" >
    <local:ConfigurationMng x:Name="ConfigMng"/>
</GroupBox>

在ConfigurationMng中,我有以下ListBox,我将其绑定到列表ConfList

<ListBox Name="lbConfigurationList" ItemsSource="{Binding ObservableConfList, UpdateSourceTrigger=PropertyChanged, diag:PresentationTraceSources.TraceLevel=High}">

我可以在ListBox中正确地看到我用构造函数创建的2元素,但是当我手动添加另一个元素时,PropertyChanged总是null。

我想我明白我必须设置一个DataContext(但我认为,如果没有手动指定,它应该使用它的父对象);

我试着手动设置:

<ListBox Name="lbConfigurationList" DataContext="{Binding [??????], RelativeSource={RelativeSource AncestorType={x:Type Window}}}" ItemsSource="{Binding ObservableConfList, UpdateSourceTrigger=PropertyChanged, diag:PresentationTraceSources.TraceLevel=High}">

但是我不知道该怎么绑定它。我现在在主窗口的数据上下文中吗?所以我在_ConfList.ConfList范围内?我应该只写Binding,我应该在正确的DataContext中,对吧?

不,即使手动添加的配置也会消失。

我在这里错过了什么?

编辑:ConfigurationMng's CodeBehind:

public partial class ConfigurationMng : UserControl
{
    public event EventHandler CreatedConfigurationEvent;
    public ConfigurationMng()
    {
        InitializeComponent();
    }
    private void AddConfiguration(object sender, RoutedEventArgs e) //Called with a button pression
    {
        if (this.CreatedConfigurationEvent != null)
        {
            this.CreatedConfigurationEvent(sender, e);
        }
    }
}

解决了,问题似乎是主ConfigurationListViewModel没有实现INotifyPropertyChanged接口,所以他只是没有通知列表框的变化。我无法写出实际的解决方案,因为我重写了项目的这一部分

绑定到父数据上下文以使用PropertyChangedEventHandler

你是正确的,它将继承父的DataContext

<ListBox Name="lbConfigurationList" DataContext="{Binding [??????], RelativeSource={RelativeSource AncestorType={x:Type Window}}}" ItemsSource="{Binding ObservableConfList, UpdateSourceTrigger=PropertyChanged, diag:PresentationTraceSources.TraceLevel=High}">

由于假设父数据上下文是继承的,因此不需要显式地为ListBox设置DataContext。你只需要确保你的ItemsSource是这样定义的

ItemsSource="{Binding ConfList.ObservableConfList, UpdateSourceTrigger=PropertyChanged, diag:PresentationTraceSources.TraceLevel=High}"

你绑定到一个ObservableCollection,你不需要INotifyPropertyChanged在你的ViewModel,因为集合已经照顾它。如果你想处理添加/删除的元素,那么你可以使用集合的CollectionChanged

另外,如果你想监听每一个项目,你的Configuration模型应该实现INotifyPropertyChanged

在我看来,你的架构增加了更多的复杂性。为什么需要创建一个单独的类来拥有一个ObservableCollection ?你可以把它放在ViewModel中,并留下你的Configuration作为你的模型