在不同的类中对属性进行绑定

时间:2018-02-23 12:53:32

标签: c# wpf xaml binding

所以我有一个班级MainViewModel我有一个按钮。该按钮导航到具有自己的视图模型的视图,让我们在ListViewModel中调用。它驻留在MainViewModel中。它有ObservableCollection名为WorkOrders

在我的主视图模型中,我有一个属性,它返回ListViewModel列表中的项目数。但是,如果我将我的按钮文本绑定到此属性(NumberOfWorkOrders),那么当WorkOrders.Count()更改时没有任何反应。即使我致电OnPropertyChanged("NumberOfWorkOrders")

但是,如果我绑定到ListViewModel中的相同属性,它确实有效。为什么它不起作用,MainViewModel中的属性?是因为来自INotifyPropertyChanged的通知在不同的视图模型中不起作用吗?

不起作用的按钮绑定(使用MainViewModel中的属性)

<Button 
    Content="{Binding NumberOfWorkOrders}" 
    ContentStringFormat="WorkOrders ({0})" />

可以工作的按钮绑定(使用ListViewModel中的属性)

<Button 
    DataContext="{Binding LVM}"
    Content="{Binding NumberOfWorkOrders}" 
    ContentStringFormat="WorkOrders ({0})" />

MainViewModel.cs

public class MainViewModel : BindableBase
{
    // INotifyPropertiesChanged is implemented in BindableBase

    private ListViewModel listViewModel = new ListViewModel();

    // This is where I would like to bind my button text to
    public int NumberOfWorkOrders
    {
        get { return listViewModel.WorkOrders.Count(); }
    }

    // I would prefer not to have this
    public ListViewModel LVM
    {
        get { return listViewModel; }
    }
}

ListViewModel.cs

public class ListViewModel : BindableBase
{
    // INotifyPropertiesChanged is implemented in BindableBase

    public ObservableCollection<WorkOrder> WorkOrders
    {
        get; set;
    }

    // I would prefer to use the version of this in the MainViewModel
    public int NumberOfWorkOrders
    {
        get { return listViewModel.WorkOrders.Count(); }
    }

    public void RefreshWorkOrders()
    {
        (...) // Load work orders and add them to collection

        OnPropertyChanged("NumberOfWorkOrders");
    }
}

2 个答案:

答案 0 :(得分:1)

您正在遇到this problem ,如果您有需要额外工作的聚合属性:您必须订阅FrameworkElement并提升ListViewModel.PropertyChanged属性的通知:

MainViewModel.NumberOfWorkOrders

第一个按钮(不起作用)有public class MainViewModel : BindableBase { readonly ListViewModel listViewModel = new ListViewModel(); public int NumberOfWorkOrders => listViewModel.WorkOrders.Count(); public MainViewModel() { // since you already rise notification in ListViewModel // listen to it and "propagate" listViewModel.PropertyChanged += (s, e) => { if(e.PropertyName == nameof(ListViewModel.NumberOfWorkOrders)) OnPropertyChanged(nameof(NumberOfWorkOrders)); }; } } 作为数据上下文,绑定只会侦听此类中的通知。

作为一个简单的修复,您可以在MainViewModel绑定中包含LVM。绑定很聪明,将开始监听两个事件:主视图模型和Path属性给出的实例:

LVM

您可以从<Button Content="{Binding LVM.NumberOfWorkOrders}" ... /> 删除NumberOfWorkOrders

答案 1 :(得分:0)

MainViewModel绑定无法正常工作的原因,因为您从OnPropertyChanged("NumberOfWorkOrders")上下文调用了ListViewModel。 我建议在MainViewModel时签署listViewModel.WorkOrders中的更改,并在OnPropertyChanged("NumberOfWorkOrders")更改MainViewModel时触发WorkOrders。您需要查看ObservableCollection的文档,以了解如何签署收集更改通知。