wpf ViewModel 属性 从另一个视图模型绑定

wpf ViewModel Property Binding from another viewmodel

我如何绑定在视图模型中声明的 属性 以从另一个视图模型中获取值?

我来解释一下

我有 2 个视图模型(实现 INotifyPropertyChanged)和 1 个视图

InvoiceView(只是我的发票设计,无论是用户控件还是 window 还是数据模板)

InvoiceViewModel

NoteListingVM(此视图模型有一个 属性 让我们将其命名为 TableRefID)

在 ViewInvoice 中,我有一个扩展器,其 dataContext 设置为 (NoteListingVM) 以显示一些 link 使用特定 invoiceID

编辑的注释

我在尝试以下操作时遇到问题

 <Expander Header="NOTES"  DockPanel.Dock="Top" Foreground="{StaticResource AlternateForeGround}">
                    <DockPanel>
                        <DockPanel.DataContext>
                            <WendBooks:NoteListingVM TableRefID="{Binding InvoiceID}" x:Name="TransactionNotes"></WendBooks:NoteListingVM>
                        </DockPanel.DataContext>

无法在 'NoteListingVM' 类型的 'TableRefID' 属性 上设置 'Binding'。 'Binding' 只能在 DependencyObject 的 DependencyProperty 上设置。

所以正如错误所说,我不能使用 属性。

然后我想使用 DependencyProperty。但是,如果您实施 InotifyPropertyChanged,DependencyProperty 将无法在 ViewModels 中正常工作。 (这是大多数用户在您实施 ViewModel 时的建议 - "INotifyPropertychanged")

当您有 userControl 或 CustomControl 时,DependencyPropertys 可以很好地工作。但这不是我的情况(我没有 usercontrol 或 customControl 我只有一个 ViewModel 我想在 InvoiceID 更改时分配/传递 "parameter" 给 NoteListingViewModel)

那么我如何将 InvoiceID(仅 xaml)发送到 NoteListingViewModel 以过滤并仅显示 link 到我前面的当前发票的注释?什么是正确的方法?我确定我错过或误解了 mvvm 模式?

不要那样做。改用 viewmodel-centric 方式:将 NoteListingVM 设为父视图模型的 属性。

不要将您的应用程序构建为拥有视图模型的视图树,而这些视图模型很难知道彼此需要什么,而是使其成为拥有自己关系的视图模型树。用除了他们自己的视图模型之外什么都不需要知道的视图来装饰它们。

请注意,下面的 InvoiceID 属性 会在更改时更新 Notes.InvoiceID。非常简单。

public MyViewModel()
{
    Notes = new NoteListingVM();
}

private int _invoiceID = 0;
public int InvoiceID
{
    get { return _invoiceID; }
    set
    {
        if (value != _invoiceID)
        {
            _invoiceID = value;
            Notes.InvoiceID = this.InvoiceID;
            OnPropertyChanged();
        }
    }
}

private NoteListingVM _notes = null;
public NoteListingVM Notes
{
    get { return _notes; }
    protected set
    {
        if (value != _notes)
        {
            _notes = value;
            OnPropertyChanged();
        }
    }
}

XAML。如果需要,您可以将 DockPanel 包裹在 ContentControl 周围。

<Expander 
    Header="NOTES"  
    DockPanel.Dock="Top" 
    Foreground="{StaticResource AlternateForeGround}"
    >
    <ContentControl Content="{Binding Notes}" />
</Expander>

候补

您还可以编写一个 NotesView UserControl,它具有 InvoiceID 依赖项 属性,并将其绑定到 XAML。它将使用相同的 NoteListingVM;你会像你一直在做的那样通过 DataContext 属性 分配它。用户控件的 InvoiceID 依赖项 属性 将有一个更改处理程序来更新视图模型的 InvoiceID,这将允许您使用绑定来设置 InvoiceID。这是一种 "proper XAML" 方法来完成您最初的想法。

您也可以将 NoteListingVM 完全重写为 UserControl,但这需要更多的工作,而且我认为它没有太多意义。

您不要在同一个 class 中混合视图模型/INotifyPropertyChanged 属性和依赖属性。