tags:

views:

39

answers:

2

Is there any way to hide a given column based on a binding. I've tried setting the visibility property on DataGridTextColumn (using the correct converter), but that doesn't seem to work. If I set the value directly (not through binding) it works. So is column visibility an all or nothing deal with the datagrid?

+1  A: 

Take a look at this post, the problem is explained
http://stackoverflow.com/questions/502389/binding-in-a-wpf-data-grid-text-column
and here
http://blogs.msdn.com/b/jaimer/archive/2008/11/22/forwarding-the-datagrid-s-datacontext-to-its-columns.aspx

Quoting JaredPar from the first link
"Essentially the problem is that the DataGridTextColumn has no parent from which to inherit a Binding because it is not a part of the logical or visual tree. You must setup an inheritance context in order to get access to the binding information"

Workaround in order to get this to work..

public class DataGridContextHelper
{
    static DataGridContextHelper()
    {
        DependencyProperty dp = FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn));
        FrameworkElement.DataContextProperty.OverrideMetadata(typeof(DataGrid),
        new FrameworkPropertyMetadata
           (null, FrameworkPropertyMetadataOptions.Inherits,
           new PropertyChangedCallback(OnDataContextChanged)));
    }

    public static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DataGrid grid = d as DataGrid;
        if (grid != null)
        {
            foreach (DataGridColumn col in grid.Columns)
            {
                col.SetValue(FrameworkElement.DataContextProperty, e.NewValue);
            }
        }
    }
}

public partial class App : Application
{
    static DataGridContextHelper dc = new DataGridContextHelper(); 
}

<DataGrid x:Name="c_dataGrid" AutoGenerateColumns="False" DataContext="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=SelectedItem}">
    <DataGrid.Columns>
        <DataGridTextColumn Visibility="{Binding Path=(FrameworkElement.DataContext), RelativeSource={x:Static RelativeSource.Self}, Converter={StaticResource HideColumnAConverter}}" />
    </DataGrid.Columns>
</DataGrid>

object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value == null)
    {
        return Visibility.Visible;
    }
    // Whatever you're binding against
    TestClass testClass = value as TestClass;
    return testClass.ColumnAVisibility;
}
Meleak
That works for the entire column...what I'm looking for is individual row control. For example, row 1 has 5 columns and row 2 has 4 columns because one of them is hidden.
AKoran
Updated my example, hopefully this will do it :) Added DataContext="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=SelectedItem}" for the DataGrid and a Converter for each column.
Meleak
Or maybe a better way to do it without the converter if you're binding against a Visibility Property. <DataGridTextColumn Binding="{Binding Value}" Visibility="{Binding Path=(FrameworkElement.DataContext).ColumnAVisibility, RelativeSource={x:Static RelativeSource.Self}}" />
Meleak
I'll give you credit since you got me thinking, but in the end there seems to be a much easier solution.
AKoran
+1  A: 

All you really have to do is add:

    <Style x:Key="vStyle" TargetType="{x:Type DataGridCell}">
        <Setter Property="Visibility" Value="{Binding YourObjectVisibilityProperty}"/>
    </Style>

and then in use the following in your columns:

<DataGridTextColumn CellStyle="{StaticResource vStyle}"/>
AKoran
Good thinking :)
Meleak