I have the following object in App.xaml
<Application.Resources>
<ResourceDictionary>
<GridView x:Key="myGridView" x:Shared="false">
<GridViewColumn Header="Created" DisplayMemberBinding="{Binding Path=Created}"/>
... more code ...
And I use this grid view in multiple places. Example:
<ListView x:Name="detailList" View="{StaticResource myGridView}" ...>
In one of the usages (such as detailList above), I'd like to hide the Created column, possibly using XAML?
Any ideas?
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> ...
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];
}
}
}
You best bet is probably to create a custom control by inheriting from the GridView class, adding the required columns, and exposing a meaningful property to show/hide a particular column. Your custom GridView class could look like this:
using System;
using System.Windows.Controls;
namespace MyProject.CustomControls
{
public class CustomGridView : GridView
{
private GridViewColumn _fixedColumn;
private GridViewColumn _optionalColumn;
public CustomGridView()
{
this._fixedColumn = new GridViewColumn() { Header = "Fixed Column" };
this._optionalColumn = new GridViewColumn() { Header = "Optional Column" };
this.Columns.Add(_fixedColumn);
this.Columns.Add(_optionalColumn);
}
public bool ShowOptionalColumn
{
get { return _optionalColumn.Width > 0; }
set
{
// When 'False' hides the entire column
// otherwise its width will be set to 'Auto'
_optionalColumn.Width = (!value) ? 0 : Double.NaN;
}
}
}
}
Then you can simply set that property from XAML like in this example:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:MyProject.CustomControls"
Title="Window1"
Height="300"
Width="300">
<StackPanel>
<ListView>
<ListView.View>
<cc:CustomGridView ShowOptionalColumn="False" />
</ListView.View>
</ListView>
<ListView>
<ListView.View>
<cc:CustomGridView ShowOptionalColumn="True" />
</ListView.View>
</ListView>
</StackPanel>
</Window>
Optionally, you could make the 'CustomGridView.ShowOptionalColumn' a DependencyProperty to be able to use it as a binding target.
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>
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();
}
}
This is my code , it works very well in my project. if you don't like to add some external code.
/// <summary>
/// show/hide datagrid column
/// </summary>
/// <param name="datagrid"></param>
/// <param name="header"></param>
private void ToggleDataGridColumnsVisible()
{
if (IsNeedToShowHideColumn())
{
foreach (GridViewColumn column in ((GridView)(this.ListView1.View)).Columns)
{
GridViewColumnHeader header = column.Header as GridViewColumnHeader;
if (header != null)
{
string headerstring = header.Tag.ToString();
if (!IsAllWaysShowingHeader(headerstring ) )
{
if (IsShowingHeader())
{
}
else
{
//hide it
header.Template = null;
column.CellTemplate = null;
column.Width = 0;
}
}
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With