wpf ViewModel属性从另一个viewmodel绑定 [英] wpf ViewModel Property Binding from another viewmodel

查看:753
本文介绍了wpf ViewModel属性从另一个viewmodel绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何绑定在ViewModel中声明的属性以从另一个ViewModel获取值?

how do i bind a property declared in a viewmodel to take value from another viewModel?

让我解释一下

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

i have 2 ViewModels (Implements INotifyPropertyChanged) and 1 View

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

InvoiceView ( just my invoice design no matter if is a user control or window or a dataTemplate)

InvoiceViewModel

InvoiceViewModel

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

NoteListingVM (this viewmodel has a property let's name it TableRefID)

在ViewInvoice中,我有一个扩展器,其dataContext设置为(NoteListingVM),以显示与特定invoiceID链接的一些注释

In the ViewInvoice i have an expander with it's dataContext set to (NoteListingVM) to show some notes that are linked with the specific invoiceID

尝试以下方法时出现问题

I have a problem when i try the following

 <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'.只能在DependencyObject的DependencyProperty上设置绑定".

A 'Binding' cannot be set on the 'TableRefID' property of type 'NoteListingVM'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

如错误所述,我无法使用属性.

so as the error said, i cannot use a property.

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

Then i think to use a DependencyProperty. But DependencyProperty cannot work properly in ViewModels if you implement an InotifyPropertyChanged. ( and this is what most users suggest when you implement a ViewModel - "INotifyPropertychanged")

当您有一个userControl或CustomControl时,DependencyPropertys可以很好地工作.但这不是我的情况(当InvoiceID更改时,我没有要分配/传递参数"给NoteListingViewModel的ViewModel,我没有userControl或customControl.

DependencyPropertys are work well when you have a userControl or CustomControl. But this is not my case(i dont have a usercontrol or customControl i only have a ViewModel that i want to assign / pass "parameter" to the NoteListingViewModel when the InvoiceID changed)

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

so how i will send the InvoiceID (only xaml) to the NoteListingViewModel to filter and show only notes that are link to the current invoice i have front on me? what is the proper way? i am sure something i missed or misunderstand the mvvm pattern?

推荐答案

不要那样做.而是以以视图模型为中心的方式进行操作:将NoteListingVM设置为父视图模型的属性.

Don't do it that way. Do it in a viewmodel-centric way instead: Make the NoteListingVM a property of the parent viewmodel.

与其将您的应用程序构造为视图树,这些视图树的视图模型难以理解彼此之间的需求,而应将其构建为拥有自己关系的视图模型树.用他们自己的视图模型将不需要的其他信息添加到花彩中.

Instead of structuring your application as a tree of views which own viewmodels that struggle to know what they need to about each other, make it a tree of viewmodels that own their own relationships. Festoon them with views that don't need to know about anything but their own viewmodels.

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

Note that the InvoiceID property below updates Notes.InvoiceID when it changes. Easy as pie.

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周围.

XAML. You could wrap a DockPanel around the ContentControl if you want.

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

备用

您还可以编写具有InvoiceID依赖项属性的NotesView UserControl,并将其绑定到XAML中.它将使用相同的NoteListingVM;您可以像以前一样通过DataContext属性进行分配.用户控件的InvoiceID依赖项属性将具有一个更改处理程序,用于更新视图模型的InvoiceID,这将使您可以使用绑定来设置InvoiceID.这是做您最初打算的适当的XAML"方法.

Alternate

You could also write a NotesView UserControl that has an InvoiceID dependency property, and bind that in the XAML. It would use the same NoteListingVM; you'd assign that via the DataContext property just as you've been doing. The user control's InvoiceID dependency property would have a change handler that updates the viewmodel's InvoiceID, which would let you use a binding to set the InvoiceID. That's a "proper XAML" way to do what you originally had in mind.

您也可以将NoteListingVM完全重写为UserControl,但这还需要更多工作,我认为它没有很多意义.

You could also entirely rewrite NoteListingVM as a UserControl, but that's more work and I don't see a whole lot of point to it.

请勿在同一类中将viewmodel/INotifyPropertyChanged属性与依赖项属性混合使用.

You don't mix viewmodel/INotifyPropertyChanged properties with dependency properties in the same class.

这篇关于wpf ViewModel属性从另一个viewmodel绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆