简体   繁体   English

wpf ViewModel属性从另一个viewmodel绑定

[英]wpf ViewModel Property Binding from another viewmodel

how do i bind a property declared in a viewmodel to take value from another viewModel? 如何绑定在ViewModel中声明的属性以从另一个ViewModel获取值?

let me explain 让我解释

i have 2 ViewModels (Implements INotifyPropertyChanged) and 1 View 我有2个ViewModel(实现INotifyPropertyChanged)和1个视图

InvoiceView ( just my invoice design no matter if is a user control or window or a dataTemplate) InvoiceView(无论我是用户控件,窗口还是dataTemplate,都只是我的发票设计)

InvoiceViewModel InvoiceViewModel

NoteListingVM (this viewmodel has a property let's name it TableRefID) NoteListingVM(此视图模型具有一个属性,让我们将其命名为TableRefID)

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 在ViewInvoice中,我有一个扩展器,其dataContext设置为(NoteListingVM)以显示与特定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>

A 'Binding' cannot be set on the 'TableRefID' property of type 'NoteListingVM'. 不能在“ NoteListingVM”类型的“ TableRefID”属性上设置“绑定”。 A 'Binding' can only be set on a DependencyProperty of a DependencyObject. 只能在DependencyObject的DependencyProperty上设置“绑定”。

so as the error said, i cannot use a property. 如错误所述,我无法使用属性。

Then i think to use a DependencyProperty. 然后,我想使用DependencyProperty。 But DependencyProperty cannot work properly in ViewModels if you implement an InotifyPropertyChanged. 但是,如果实现InotifyPropertyChanged,则DependencyProperty将无法在ViewModels中正常工作。 ( and this is what most users suggest when you implement a ViewModel - "INotifyPropertychanged") (这是大多数用户在实施ViewModel时的建议-“ INotifyPropertychanged”)

DependencyPropertys are work well when you have a userControl or CustomControl. 当您拥有userControl或CustomControl时,DependencyPropertys可以很好地工作。 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更改时,我没有要分配/传递“参数”给NoteListingViewModel的ViewModel,我没有userControl或customControl。)

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? 因此,我如何将InvoiceID(仅xaml)发送到NoteListingViewModel进行过滤并仅显示与当前发票相关联的注释,而这些注释却在我眼前? what is the proper way? 正确的方法是什么? i am sure something i missed or misunderstand the mvvm pattern? 我确定我错过或误解了mvvm模式吗?

Don't do it that way. 不要那样做。 Do it in a viewmodel-centric way instead: Make the NoteListingVM a property of the parent viewmodel. 而是以以视图模型为中心的方式进行操作:将NoteListingVM设置为父视图NoteListingVM的属性。

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. 用他们自己的视图模型将不需要的其他信息添加到花彩中。

Note that the InvoiceID property below updates Notes.InvoiceID when it changes. 请注意,下面的InvoiceID属性在更改时会更新Notes.InvoiceID 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. XAML。 You could wrap a DockPanel around the ContentControl if you want. 如果需要,可以将DockPanel包裹在ContentControl周围。

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

Alternate 备用

You could also write a NotesView UserControl that has an InvoiceID dependency property, and bind that in the XAML. 您还可以编写具有InvoiceID依赖项属性的NotesView UserControl ,并将其绑定到XAML中。 It would use the same NoteListingVM ; 它将使用相同的NoteListingVM ; you'd assign that via the DataContext property just as you've been doing. 您可以像以前一样通过DataContext属性进行分配。 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 . 用户控件的InvoiceID依赖项属性将具有一个更改处理程序,用于更新视图模型的InvoiceID ,这将使您可以使用绑定来设置InvoiceID That's a "proper XAML" way to do what you originally had in mind. 这是做您最初打算的“适当的XAML”方法。

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. 您也可以将NoteListingVM完全重写为UserControl ,但这还需要更多工作,我对此没有多大意义。

You don't mix viewmodel/ INotifyPropertyChanged properties with dependency properties in the same class. 您不要在同一类中将viewmodel / INotifyPropertyChanged属性与依赖项属性混合使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM