Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind to DataContext Property from within DataGridColumn

Property Foo is in my DataContext

ViewModel {
    Visibility Foo;
}


But I cannot figure out how to access Foo inside a Column. In this case, I assume it's probably looking for Foo in whatever object is bound to the DataGrid ItemsSource

<DataGrid Visibility="{Binding Foo}">                      // works
    <DataGrid.Columns>
        <DataGridTextColumn Visibility="{Binding Foo}" />   // fails


I have tried

Binding="{Binding DataContext.Foo}"

And a bunch of things with RelativeSource tags as well.


Also, is there some way to view and select a property to bind to from a GUI?

Edit: It turns out that the Columns themselves are not FrameworkElements, so they cannot locate the DataGrid ancestor. You can however use the technique in the answer below to bind properties of the CellTemplate of the Column to the DataContext.

like image 910
Matt Avatar asked Feb 15 '23 19:02

Matt


2 Answers

This should work:

<DataGridTextColumn Visibility="{Binding Path=DataContext.Foo, RelativeSource={RelativeSource AncestorType=DataGrid}}" />

You're right about the column being bound to the current item - that's why you need to use RelativeSource to get the DataGrid, and then access the Foo property in its DataContext.

As for selecting the property to bind to, there's the WPF designer's properties panel and visual studio addons such as Resharper which can help, but eventually they don't do such a great job at anything other than simple bindings, so what you're left with is yourself and your understanding of what's going on.

like image 123
Adi Lester Avatar answered Feb 18 '23 08:02

Adi Lester


I found a few approaches to binding outside of the visual tree from this article: Artificial Inheritance Contexts in WPF

I am using yet a fourth option (related to what he suggests). It is fairly hacky but simple. It has the downside that the WPF designer does not like it and puts errors in your error log during design time. In order to get to the ambient DataContext, you can bind to something else in the current XAML file that IS in the visual tree, using the x:Reference markup extension (see msdn). This is similar to binding by ElementName except that it is not dependent on having an InheritanceContext, which you typically don't outside of the visual tree. I just use a dummy FrameWorkElement if there is nothing else in the UserControl to reference.

I tried to just reference the containing UserControl (or Window or Page, etc) but this leads to a circular reference exception, so I live with the dummy element until someone shows me a better way.

<FrameworkElement Name="dummyElement" />
<DataGrid>
    <DataGrid.Columns>
        <DataGridTextColumn 
           Visibility="{Binding Source={x:Reference dummyElement}, 
                                Path=DataContext.Foo}" 
        />
like image 20
TCC Avatar answered Feb 18 '23 07:02

TCC