WPF绑定到父DataContext

时间:2012-11-16 11:25:35

标签: c# wpf binding

我们有一个带有标准MVVM模式的WPF应用程序,利用Cinch(以及MefedMVVM)进行View - > ViewModel分辨率。这很有效,我可以将相关控件绑定到ViewModel上的属性。

在特定的视图中,我们有一个Infragistics XamGrid。此网格绑定到ViewModel上的ObservableCollection,并显示相应的行。但是,我在这个网格上有一个特定的列,我试图将TextBox文本值绑定到父DataContext上的属性,而不是ObservableCollection。这种绑定失败了。

我们在这里经历了几个选项,包括:

  1. 使用AncestorType跟踪树并绑定到父UserControl的DataContext,如此(从great answer到此问题,以及this one)......

    {Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
    
  2. 指定ElementName并尝试直接定位顶级控件。如果您想阅读有关使用ElementName的信息,请设置look here

  3. 使用UserControl资源中定义的'proxy'FrameorkElement尝试根据需要“传入”上下文。我们将元素定义如下,然后引用为静态资源......

    <FrameworkElement x:Key="ProxyContext" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource Self}}"></FrameworkElement>
    
  4. 在这种情况下,绑定会找到FrameworkElement,但不能访问除此之外的任何内容(指定Path时)。

    阅读后,很可能这是由树外的Infragistics XamGrid构建列引起的。但是,即使是这种情况,至少应该使用选项2或3。

    我们最后的想法是它与V-VM绑定有关,但即使使用Snoop,我们还没有找到确切的问题。我绝不是WPF绑定的专家,所以任何指针都会受到赞赏。

    编辑:我已经从Infragistics here找到了一些我将尝试的模板示例。

    编辑2:正如@Dtex所指出的,模板是可行的方法。以下是与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>
    

    我已经打开了XML ...您只需添加所需的列,然后关闭相关标签。

2 个答案:

答案 0 :(得分:78)

我不知道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>

由于单元格模板中指定的TextBlockTextBox将成为可视树的一部分,因此您可以向上走,找到您需要的任何控件。

答案 1 :(得分:0)

由于这样的事情,作为一般的经验法则,我尽量避免尽可能多的XAML“欺骗”并尽可能保持XAML的愚蠢和简单,并在ViewModel(或附加属性或IValueConverters等,如果真的有必要)。

如果可能的话,我会给当前DataContext的ViewModel一个引用(即属性)到相关的父ViewModel

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

直接绑定它。

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