简体   繁体   English

WPF绑定到父DataContext

[英]WPF Binding to parent DataContext

We have a WPF application with a standard MVVM pattern, leveraging Cinch (and therefore MefedMVVM) for View -> ViewModel resolution. 我们有一个带有标准MVVM模式的WPF应用程序,利用Cinch(以及MefedMVVM)进行View - > ViewModel解析。 This works well, and I can bind the relevant controls to properties on the ViewModel. 这很好用,我可以将相关控件绑定到ViewModel上的属性。

Within a particular View, we have an Infragistics XamGrid. 在特定的视图中,我们有一个Infragistics XamGrid。 This grid is bound to an ObservableCollection on the ViewModel, and displays the appropriate rows. 此网格绑定到ViewModel上的ObservableCollection,并显示相应的行。 However, I then have a specific column on this grid which I am trying to bind a TextBox text value to a property on the parent DataContext, rather than the ObservableCollection. 但是,我在这个网格上有一个特定的列,我试图将TextBox文本值绑定到父DataContext上的属性,而不是ObservableCollection。 This binding is failing. 这种绑定失败了。

We've gone through several options here including: 我们在这里经历了几个选项,包括:

  1. Using AncestorType to track up the tree and bind to the DataContext of the parent UserControl like so (from the great answer to this question, as well as this one )... 使用AncestorType跟踪树并绑定到父UserControl的DataContext,如此(从这个问题的答案很好,以及这个 )...

     {Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}} 
  2. Specifying the ElementName and trying to target the top level control directly. 指定ElementName并尝试直接定位顶级控件。 Have a look here if you'd like to read about using ElementName. 如果您想阅读有关使用ElementName的信息,请查看此处

  3. Using a 'proxy' FrameorkElement defined in the resources for the UserControl to try and 'pass in' the context as required. 使用UserControl资源中定义的“代理”FrameorkElement尝试根据需要“传入”上下文。 We define the element as below, then reference as a static resource... 我们将元素定义如下,然后作为静态资源引用...

     <FrameworkElement x:Key="ProxyContext" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource Self}}"></FrameworkElement> 

In this case the binding finds the FrameworkElement, but can not access anything beyond that (when specifying a Path). 在这种情况下,绑定会找到FrameworkElement,但不能访问除此之外的任何内容(指定Path时)。

Having read around, it looks quite likely that this is caused by the Infragistics XamGrid building columns outside of the tree. 阅读之后,很可能这是由树外的Infragistics XamGrid构建列引起的。 However, even if this is the case, at least options 2 or 3 should work. 但是,即使是这种情况,至少应该选择2或3。

Our last thoughts are that it is related to the V - VM binding, but even using Snoop we've yet to find what the exact issue is. 我们最后的想法是它与V-VM绑定有关,但即使使用Snoop,我们还没有找到确切的问题。 I'm by no means an expert with WPF binding so any pointers would be appreciated. 我绝不是WPF绑定的专家所以任何指针都会受到赞赏。

EDIT: I have found some templating examples from Infragistics here that I will try. 编辑:我在这里找到了一些来自Infragistics的模板示例,我将尝试。

EDIT 2: As pointed out by @Dtex, templates are the way to go. 编辑2:正如@Dtex所指出的,模板是可行的方法。 Here is the relevant snippet for use with a XamGrid: 以下是与XamGrid一起使用的相关代码段:

<ig:GroupColumn Key="CurrentDate">
                <ig:GroupColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=DataContext.CurrentDateTest, RelativeSource={RelativeSource AncestorType=UserControl}}" />
                    </DataTemplate>
                </ig:GroupColumn.HeaderTemplate>
                <ig:GroupColumn.Columns>

I've left the XML open... you'd simply add the columns you wanted, then close off the relevant tags. 我已经打开了XML ...你只需要添加你想要的列,然后关闭相关的标签。

I dont know about XamGrid but that's what i'll do with a standard wpf DataGrid : 我不知道XamGrid但这就是我用标准的wpf DataGrid做的事情:

<DataGrid>
    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding DataContext.MyProperty, RelativeSource={RelativeSource AncestorType=MyUserControl}}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding DataContext.MyProperty, RelativeSource={RelativeSource AncestorType=MyUserControl}}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

Since the TextBlock and the TextBox specified in the cell templates will be part of the visual tree, you can walk up and find whatever control you need. 由于单元格模板中指定的TextBlockTextBox将成为可视树的一部分,因此您可以向上走,找到所需的控件。

Because of things like this, as a general rule of thumb, I try to avoid as much XAML "trickery" as possible and keep the XAML as dumb and simple as possible and do the rest in the ViewModel (or attached properties or IValueConverters etc. if really necessary). 由于这样的事情,作为一般的经验法则,我尽量避免尽可能多的XAML“欺骗”并尽可能保持XAML的愚蠢和简单,并在ViewModel(或附加属性或IValueConverters等)中完成其余工作。如果真的有必要)。

If possible I would give the ViewModel of the current DataContext a reference (ie property) to the relevant parent ViewModel 如果可能的话,我会给当前DataContext的ViewModel一个引用(即属性)给相关的父ViewModel

public class ThisViewModel : ViewModelBase
{
    TypeOfAncestorViewModel Parent { get; set; }
}

and bind against that directly instead. 并直接绑定它。

<TextBox Text="{Binding Parent}" />

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

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