1

I have a UserControl with its DataContext set to another class called HostConext.

In HostContext I have the following property:

public Visibility IsOutcomesVisible
{
  get { return _isOutcomesVisible; }
  set { _isOutcomesVisible = value; OnPropertyChanged("IsOutcomesVisible"); }
}

My XAML contains a DataGrid that looks like this:

<dg:DataGrid Grid.Row="0" ItemsSource="{Binding Path=Payments}">
  <dg:DataGrid.Columns>
    <dg:DataGridTextColumn Header="Payment Date" Binding="{Binding PaymentDate,StringFormat={}\{0:yyyy/MM/dd\}}"/>
    <dg:DataGridComboBoxColumn Header="Outcome" SelectedItemBinding="{Binding Outcome}" 
        Visibility="{Binding Path=DataContext.IsOutcomesVisible}">
      ....
    </dg:DataGridComboBoxColumn>
  </dg:DataGrid.Columns>
</dg:DataGrid>

The datagrid's ItemSource is set to an ObservableList of Payment objects and each column binds the properties in it. The problem, however, is that I need to hide (or disable) the Outcomes column based on a property in the UserControl's DataContext.

Does anybody here know how this can be achieved? I really don't want to put the "IsOutcomesVisible" property in the Payments class :(

Andre
  • 1,107
  • 11
  • 22

4 Answers4

2

Try using Josh Smith's DataContextSpy to introduce an artificial inheritance context to your DataGridColumn

http://blogs.infragistics.com/blogs/josh_smith/archive/2008/06/26/data-binding-the-isvisible-property-of-contextualtabgroup.aspx

public class DataContextSpy
    : Freezable // Enable ElementName and DataContext bindings
{
    public DataContextSpy()
    {
        // This binding allows the spy to inherit a DataContext.
        BindingOperations.SetBinding(this, DataContextProperty, new Binding());
    }

    public object DataContext
    {
        get { return (object)GetValue(DataContextProperty); }
        set { SetValue(DataContextProperty, value); }
    }

    // Borrow the DataContext dependency property from FrameworkElement.
    public static readonly DependencyProperty DataContextProperty =
        FrameworkElement.DataContextProperty.AddOwner(typeof(DataContextSpy));

    protected override Freezable CreateInstanceCore()
    {
        // We are required to override this abstract method.
        throw new NotImplementedException();
    }
}

So you add one of these to the control/page/window's resource dictionary like this:

<UserControl.Resources>
     <misc:DataContextSpy x:Key="Spy" />
</UserControl.Resources>

Now you can reference the spy through a StaticResourceExtension to get to the control/page/window's data context

 Visibility="{Binding 
                 Source={StaticResource Spy}, 
                 Path=DataContext.IsOutcomesVisible}"
cordialgerm
  • 8,403
  • 5
  • 31
  • 47
1

Change your visibility binding to something like:

Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.IsOutcomesvisible}"

Similar Question

Community
  • 1
  • 1
Nick Heidke
  • 2,787
  • 2
  • 34
  • 58
  • Not working :( I've put a break point on the setter and it is definitely set to Hidden, but the code never reaches the get. I did fix the DataGrid part to dg:DataGrid and IsOutcomesvisible to IsOutcomesVisible. Nothing. – Andre Jul 05 '11 at 15:29
  • Can you try changing AncestorType={x:Type DataGrid}} to point to the highest level container? Maybe a StackPanel or Grid? – Nick Heidke Jul 05 '11 at 15:33
  • Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type Grid}}, Path=DataContext.IsOutcomesVisible}"> -- didn't work either – Andre Jul 05 '11 at 15:42
0

RelativeSource can be tricky if you have multiple DataGrids in your View, how about this:

Visibility="{Binding ElementName=windowMain, Path=DataContext.IsOutcomesVisible}

Make sure to name your Window or Control where you are assinging your initial DataContext

Bek Raupov
  • 3,782
  • 3
  • 24
  • 42
  • I tried this. No luck. Should I use it in combination with the above answer? – Andre Jul 05 '11 at 15:48
  • can u ensure ElementName that you are providing is the same Element that you are attaching DataContext when you initialize. Did simple test and it worked in my case – Bek Raupov Jul 05 '11 at 15:52
  • I added and in it's constructor this.DataContext = myContext; EDIT: I tried it with Name instead of x:Name as well. – Andre Jul 05 '11 at 15:54
  • can u please the Output window for any errors, usually displays any Binding Errors – Bek Raupov Jul 05 '11 at 15:57
  • OUTPUT: Cannot find governing FrameworkElement or FrameworkContentElement for target element – Andre Jul 05 '11 at 16:02
  • copy and paste error, replaced ItemsSource with Visibility, can u confirm is other bindings working fine? – Bek Raupov Jul 05 '11 at 16:08
0

this answer is more similar to NickHeidke's answer i just added "Mode=FindAncestor" and in X:Type use dg:DataGrid

Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type dg:DataGrid}}, Path=DataContext.IsOutcomesvisible}"
Bathineni
  • 3,436
  • 18
  • 25