How to Hide Wpf Datagrid Columns Depending on a Property

How to hide wpf datagrid columns depending on a property

A column in a datagrid is an abstract object which does not appear in the visual tree, thus you cannot use RelativeSource-binding, ElementName will not work either since it will not find a governing FrameworkContentElement so you are in kind of a bind.

One way that works is via Source and x:Reference, for that you will need to name your window and move the column to its resources to avoid a cyclical dependency error:

<Window Name="_window" ...>
<Window.Resources>
<DataGridTextColumn x:Key="ThatPeskyColumn"
Binding="{Binding Size}"
Visibility="{Binding DataContext.Flag, Source={x:Reference _window}, Converter={StaticResource BoolToVis}}"/>
</Window.Resources>
<!-- ... -->
<DataGrid AutoGenerateColumns="False" Name="Blumen"
ItemsSource="{Binding Leaves}">
<DataGrid.Columns>
<StaticResource ResourceKey="ThatPeskyColumn"/>
<!-- ... -->

Great fun.

Hide Datagrid Column based on its Property name

You could handle the DataGrid.AutoGeneratedColumns Event and set the column's Visibility property from there. You should be able to do something like this:

private void DataGridAutoGeneratingColumn(object sender, 
DataGridAutoGeneratingColumnEventArgs e)
{
DataGrid dataGrid = sender as DataGrid;
if (dataGrid != null && IsBKM) dataGrid.Columns[0].Visible = false;
}

UPDATE >>>

You can use the e.Column.Header property to check the name of the column and then use that instead. However, your column has no Header currently set. You could also set the column name (in XAML) and then check for that Name value instead of using the Header property:

private void DataGridAutoGeneratingColumn(object sender, 
DataGridAutoGeneratingColumnEventArgs e)
{
if (e.Column.Name == "IsBKM" && IsBKM)
{
e.Column.Visibility = Visibility.Collapsed;
}
}

Hide a Column from a DataGrid when the ItemSource is an Observable Collection

This issue will happen regardless of whether the data resides in an ObservableCollection or not.

To correct this, one must set the grid to not auto generate the columns. That is done by setting the property AutoGenerateColumns=False and then in the xaml specify the columns desired.

<DataGrid ItemsSource="{Binding  MyData}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="The Code"
Binding="{Binding Code}"/>
<DataGridTextColumn Header="The Name"
Binding="{Binding Name}"/>
<DataGridTextColumn Header="The Type"
Binding="{Binding Type}"/>
</DataGrid.Columns>
</DataGrid>

Check out more column options in the documentation for the DataGrid.

Show/Hide DataGrid Columns XAML

Was able to find some more information on this. This link has a good answer/explanation.
datagridtextcolumn-visibility-binding

It turns out that the columns of a DataGrid do not appear in the visual tree of a DataGrid.

But the answer is to use x:reference in the visibility binding, and a BooleanToVisibilityConverter:

<DataGridTextColumn Header="Customer #" x:Name="CustNum_Col" Visibility="{Binding Source={x:Reference VisibilityCheck}, Path=IsChecked,Converter={StaticResource ObjectToVisibilityConverter}}" />

Visual Studio will show the squiggly line under the binding saying that "object not set to instance of an object" but it this still appears to work.

MVVM - Hide Datagrid column based on column name with autogeneratecolumns = True

I found a solution by applying this style:

<Style x:Key="ColumnStyle" TargetType="DataGridColumnHeader">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Value}" Value="id">
<Setter Property="Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>

to DataGridCell and to DataGridColumnHeader and allocating the column in the end of the table this removed the empty column from the middle of the table.

Hiding DataGrid Column based on Column values

You need to check each value in the DataGridTextColumn and set Column.Visibility accordingly.
To wrap all the logic I've derived from DataGrid.

public class MyDataGrid : DataGrid
{
private void ValidateColumnVisibility()
{
if (Items.Count == 0 || Items[0] == CollectionView.NewItemPlaceholder) return;
var itemClass = Items[0].GetType();
foreach (var column in Columns)
{
if (column.GetType() == typeof(DataGridTextColumn))
{
// find the property that this column is bound to
DataGridBoundColumn boundColumn = column as DataGridBoundColumn;
Binding binding = boundColumn.Binding as Binding;
string boundPropertyName = binding.Path.Path;
var prop = itemClass.GetProperty(boundPropertyName);

// Validating Column.Visibility when first value is null
// when all values are null -> Visibility.Collapsed
// bound value not a string -> Visibility.Visible
// all bound strings empty -> Visibility.Collapsed
if (prop.GetValue(Items[0]) == null)
{
column.Visibility = Visibility.Collapsed;
foreach (var item in Items)
{
if (item != CollectionView.NewItemPlaceholder)
{
if (prop.GetValue(item) != null)
{
if (prop.GetValue(item).GetType() != typeof(String))
column.Visibility = Visibility.Visible;
else if (String.IsNullOrEmpty(prop.GetValue(item) as String) == false)
column.Visibility = Visibility.Visible;
}
}
}
}

// First value not null and all bound strings empty -> Visibility.Collapsed
else if (prop.GetValue(Items[0]).GetType() == typeof(String))
{
column.Visibility = Visibility.Collapsed;
foreach (var item in Items)
{
if (item != CollectionView.NewItemPlaceholder)
{
if (String.IsNullOrEmpty(prop.GetValue(item) as String) == false)
column.Visibility = Visibility.Visible;
}
}
}
}
}
}

protected override void OnItemsSourceChanged(
IEnumerable oldValue, IEnumerable newValue)
{
base.OnItemsSourceChanged(oldValue, newValue);
ValidateColumnVisibility();
}

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
ValidateColumnVisibility();
}
}

Using MyDataGrid you no longer need to set Column.Visibility in XAML as it happens automagically.



Related Topics



Leave a reply



Submit