4

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.

Matt
  • 5,461
  • 7
  • 36
  • 43
  • Can you elaborate more what you mean by "select a property to bind"? Or at least what the desired effect is? – tHand Jul 25 '13 at 20:34
  • I was wondering if theres a way to view and select items from say, a treeview, rather than having to remember how to write all the Path/RelativeSource/DataContext/etc tags – Matt Jul 26 '13 at 14:46
  • I agree you can use the `RelativeSource` binding in Adi's answer on a `CellTemplate`... if you like that solution then I think you should post it as a solution and mark it as the answer, since Adi's code does not work without the key provision of using a `CellTemplate`. Someone browsing this question might reasonably look at the marked "answer" and assume it works without reading your comments to the contrary. I added a method to bind the visibility of the column, rather than hide cells using the `CellTemplate`. – TCC Nov 20 '13 at 22:40

2 Answers2

4

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}" 
        />
TCC
  • 2,546
  • 1
  • 24
  • 35
3

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.

Adi Lester
  • 24,731
  • 12
  • 95
  • 110
  • See my edit above. It looks like the technique is correct, but because columns are not FrameworkElements, this still fails. – Matt Jul 26 '13 at 15:29
  • 1
    This doesn't appear to work as noted by the OP. So why is it the answer? – user99999991 Jul 16 '16 at 02:02
  • x:reference seems to be the only way to do it. http://stackoverflow.com/questions/22073740/binding-visibility-for-datagridcolumn-in-wpf – user99999991 Jul 16 '16 at 02:09