C# 使绑定在不同类中的属性上工作

C# 使绑定在不同类中的属性上工作,c#,wpf,xaml,binding,C#,Wpf,Xaml,Binding,因此,我有一个类MainViewModel,其中有一个按钮。该按钮导航到具有自己视图模型的视图,让我们调用ListViewModel。它位于MainViewModel内部。它有一个名为WorkOrders的ObservableCollection 在我的主视图模型中,我有一个属性,它返回ListViewModel中列表中的项数。但是,如果我将按钮文本绑定到此属性(NumberOfWorkOrders),则当WorkOrders.Count()更改时,不会发生任何事情。即使我调用OnPropert

因此,我有一个类
MainViewModel
,其中有一个按钮。该按钮导航到具有自己视图模型的视图,让我们调用
ListViewModel
。它位于MainViewModel内部。它有一个名为
WorkOrders
ObservableCollection

在我的主视图模型中,我有一个属性,它返回ListViewModel中列表中的项数。但是,如果我将按钮文本绑定到此属性(
NumberOfWorkOrders
),则当
WorkOrders.Count()
更改时,不会发生任何事情。即使我调用
OnPropertyChanged(“NumberOfWorkOrders”)

但是,如果我绑定到ListViewModel中的相同属性,它确实可以工作。为什么在MainViewModel中的属性不起作用?是否因为INotifyPropertyChanged的通知在其他视图模型中不起作用

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

ListViewModel.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; }
    }
}
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");
    }
}
公共类ListViewModel:BindableBase
{
//INotifyPropertiesChanged在BindableBase中实现
公众可观察收集工作单
{
获得;设置;
}
//我更喜欢在MainViewModel中使用此版本
公共国际号码
{
获取{return listViewModel.WorkOrders.Count();}
}
公共订单()
{
(…)//加载工单并将其添加到集合中
关于财产变更(“工作订单数量”);
}
}

您的
MainViewModel
绑定无法工作的原因是,您从
ListViewModel
上下文调用了
OnPropertyChanged(“NumberOfWorkOrders”)
。 我建议在
MainViewModel
中对
listViewModel.WorkOrders
中的更改进行签名,并在
WorkOrders
更改时,从
MainViewModel
对属性更改(“NumberOfWorkOrders”)
发出
。您需要查看
ObservableCollection
的文档,以找到如何签署已更改的收款通知。

您遇到了 ,其中您有需要额外作业的聚合属性:您必须订阅
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));
        };
    }
}
<Button Content="{Binding LVM.NumberOfWorkOrders}" ... />
第一个按钮(不起作用)将
MainViewModel
作为数据上下文,绑定将只侦听此类中的通知

作为一个简单的修复,您可以在绑定的
Path
中包含
LVM
。绑定是智能的,将开始侦听两个事件:主视图模型的事件和由
LVM
property给出的实例的事件:

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));
        };
    }
}
<Button Content="{Binding LVM.NumberOfWorkOrders}" ... />


您可以从
MainViewModel
中删除
NumberOfWorkOrders

请参见您需要实现
inotifPropertyChanged
@Decoder94我已经在我的
BindableBase
类中实现了
inotifPropertyChanged
,这是由两个视图模型继承的。我还应该在哪里实现它?它是绑定的源,即定义NumberOfWorkOrders属性的类,需要引发PropertyChanged事件。谢谢,它可以工作。除了一件事。我不允许在
MainViewModel()
中的构造函数中使用
nameof()。我可以通过将属性的名称键入字符串来解决问题,所以唯一真正的问题是我的混淆。。。