I have the following object in App.xaml
<GridViewColumn Width="{Binding Tag, RelativeSource={RelativeSource AncestorType=ListView}, Converter={converters:BooleanToWidthConverter}, ConverterParameter=100}">
<GridViewColumn.HeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource ColumnHeaderStyle}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource AncestorType=ListView}}" Value="true">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</GridViewColumn.HeaderContainerStyle>
<GridViewColumn.Header>
<StackPanel Tag="columnHeader" Orientation="Horizontal">
</StackPanel>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentControl>
<TextBlock Text="test" />
</ContentControl>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
class BooleanToWidthConverter :IValueConverter {
public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool b)
{
return b ? parameter : 0;
}
return 0;
}
public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
Unfortunately, there is no "IsVisible" Property in GridViewColumn But, I have a solution can solve this problem by simple and complete way:
Code sample above:
Taken from here
<ListView Grid.Column="1" Grid.Row="1" Name="FicheList" >
<ListView.Resources>
<ResourceDictionary>
<Style x:Key="hiddenStyle" TargetType="GridViewColumnHeader">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
</ResourceDictionary>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Code}" Header="Code" Width="0" HeaderContainerStyle="{StaticResource hiddenStyle}" />
<GridViewColumn DisplayMemberBinding="{Binding FicheTitle}" Header="Title" Width="100" />
<GridViewColumn DisplayMemberBinding="{Binding CategoryName}" Header="Category" Width="100" />
<GridViewColumn DisplayMemberBinding="{Binding UpdateDate}" Header="Update Date" Width="100" />
</GridView>
</ListView.View>
</ListView>
Based on Ben McMillan's answer, but supports dynamic changing of visible property. I've simplified his solution further by removing the IsEnabled property.
public class GridViewColumnVisibilityManager
{
static Dictionary<GridViewColumn, double> originalColumnWidths = new Dictionary<GridViewColumn, double>();
public static bool GetIsVisible(DependencyObject obj)
{
return (bool)obj.GetValue(IsVisibleProperty);
}
public static void SetIsVisible(DependencyObject obj, bool value)
{
obj.SetValue(IsVisibleProperty, value);
}
public static readonly DependencyProperty IsVisibleProperty =
DependencyProperty.RegisterAttached("IsVisible", typeof(bool), typeof(GridViewColumnVisibilityManager), new UIPropertyMetadata(true, OnIsVisibleChanged));
private static void OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
GridViewColumn gc = d as GridViewColumn;
if (gc == null)
return;
if (GetIsVisible(gc) == false)
{
originalColumnWidths[gc] = gc.Width;
gc.Width = 0;
}
else
{
if (gc.Width == 0)
gc.Width = originalColumnWidths[gc];
}
}
}
I have a much simpler solution than using an Attached Behavior.
All you have to do is bind the Width Property of the GridViewColumn to a boolean on your ViewModel. Then create a simple Converter like BooleanToWidthConverter that takes a boolean and returns a double, zero if its false, x width if its true.
I hope this helps and makes your life easier.
XAML:
<GridViewColumn x:Name="MyHiddenGridViewColumn"
Width={Binding Path=IsColumnVisibleProperty, Converter={StaticResource BooleanToWidthConverter}}">
<!-- GridViewColumn.HeaderTemplate etc. goes here. -->
</GridViewColumn>
Converter:
public class BooleanToWidthConverter : IValueConverter
{
private const double Column_Width = 40.0;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value != DependencyProperty.UnsetValue)
{
bool isVisible = (bool) value;
return isVisible ? Column_Width : 0;
}
return Column_Width;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I'd suggest using a custom property (or hijacking an existing one) on the parent and then using a custom style on the gridviewcolumnheader to reference that ancestor property. Like this:
<Window.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=Tag}"/>
</Style>
<GridView x:Key="myGridView" x:Shared="false">
<GridViewColumn Header="Created" DisplayMemberBinding="{Binding Path=Created}"/>
</GridView>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<StackPanel>
<ListView x:Name="detailList" View="{StaticResource myGridView}"/>
<ListView x:Name="detailListHide" Tag="{x:Static Member=Visibility.Hidden}" View="{StaticResource myGridView}"/>
</StackPanel>
</Grid>
Actually, I find the easiest solution is via attached properties:
public class GridViewColumnVisibilityManager
{
static void UpdateListView(ListView lv)
{
GridView gridview = lv.View as GridView;
if (gridview == null || gridview.Columns == null) return;
List<GridViewColumn> toRemove = new List<GridViewColumn>();
foreach (GridViewColumn gc in gridview.Columns)
{
if (GetIsVisible(gc) == false)
{
toRemove.Add(gc);
}
}
foreach (GridViewColumn gc in toRemove)
{
gridview.Columns.Remove(gc);
}
}
public static bool GetIsVisible(DependencyObject obj)
{
return (bool)obj.GetValue(IsVisibleProperty);
}
public static void SetIsVisible(DependencyObject obj, bool value)
{
obj.SetValue(IsVisibleProperty, value);
}
public static readonly DependencyProperty IsVisibleProperty =
DependencyProperty.RegisterAttached("IsVisible", typeof(bool), typeof(GridViewColumnVisibilityManager), new UIPropertyMetadata(true));
public static bool GetEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(EnabledProperty);
}
public static void SetEnabled(DependencyObject obj, bool value)
{
obj.SetValue(EnabledProperty, value);
}
public static readonly DependencyProperty EnabledProperty =
DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(GridViewColumnVisibilityManager), new UIPropertyMetadata(false,
new PropertyChangedCallback(OnEnabledChanged)));
private static void OnEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
ListView view = obj as ListView;
if (view != null)
{
bool enabled = (bool)e.NewValue;
if (enabled)
{
view.Loaded += (sender, e2) =>
{
UpdateListView((ListView)sender);
};
view.TargetUpdated += (sender, e2) =>
{
UpdateListView((ListView)sender);
};
view.DataContextChanged += (sender, e2) =>
{
UpdateListView((ListView)sender);
};
}
}
}
}
Then, it can be used as so:
<ListView foo:GridViewColumnVisibilityManager.Enabled="True">
...
<GridViewColumn Header="Status" foo:GridViewColumnVisibilityManager.IsVisible="{Binding ShowStatusColumn}">
<GridViewColumn.CellTemplate>
<DataTemplate> ...