WPF: Как скрыть GridViewColumn с помощью XAML?
У меня есть следующий объект в App.xaml
<Application.Resources>
<ResourceDictionary>
<GridView x:Key="myGridView" x:Shared="false">
<GridViewColumn Header="Created" DisplayMemberBinding="{Binding Path=Created}"/>
... more code ...
И я использую это представление сетки в нескольких местах. Пример:
<ListView x:Name="detailList" View="{StaticResource myGridView}" ...>
В одном из способов использования (например, detailList выше) я хотел бы скрыть столбец "Создать", возможно, используя XAML?
Любые идеи?
Ответы
Ответ 1
Фактически, я нахожу, что самое легкое решение - через прикрепленные свойства:
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);
};
}
}
}
}
Затем его можно использовать так:
<ListView foo:GridViewColumnVisibilityManager.Enabled="True">
...
<GridViewColumn Header="Status" foo:GridViewColumnVisibilityManager.IsVisible="{Binding ShowStatusColumn}">
<GridViewColumn.CellTemplate>
<DataTemplate> ...
Ответ 2
На основании ответа Бена Макмиллана, но поддерживает динамическое изменение видимого свойства.
Я упростил его решение, удалив свойство IsEnabled.
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];
}
}
}
Ответ 3
Лучше всего создать настраиваемый элемент управления, наследуя класс GridView, добавляя необходимые столбцы и выставляя значимое свойство для отображения/скрытия определенного колонка. Ваш собственный класс GridView может выглядеть следующим образом:
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;
}
}
}
}
Затем вы можете просто установить это свойство из XAML, как в этом примере:
<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>
Необязательно, вы можете сделать "CustomGridView.ShowOptionalColumn" DependencyProperty, чтобы использовать его как цель привязки.
Ответ 4
Взято из здесь
<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>
Ответ 5
Это мой код, он очень хорошо работает в моем проекте. если вам не нравится добавлять внешний код.
/// <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;
}
}
}
}
}
}
Ответ 6
Я бы предложил использовать настраиваемое свойство (или захват существующего) для родителя, а затем использовать собственный стиль в gridviewcolumnheader для ссылки на это свойство предка. Вот так:
<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>
Ответ 7
В небольшой утилите, которую я написал, у меня есть список, в котором пользователь может скрывать/показывать некоторые столбцы. В столбцах нет свойства видимости, поэтому я решил установить ширину скрытых колонок равными нулю. Не идеально, так как пользователь может изменить их размер и сделать их видимыми снова.
В любом случае, для этого я использовал:
<GridViewColumn.Width>
<MultiBinding Converter="{StaticResource WidthConverter}" Mode="TwoWay">
<Binding Path="ThreadIdColumnWidth" Mode="TwoWay" />
<Binding Path="IsThreadIdShown" />
</MultiBinding>
</GridViewColumn.Width>
IsThreadIdShown
привязан к флажку на панели инструментов.
И многозначный конвертер:
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
if (values.Length != 2) {
return null;
}
object o0 = values[0];
object o1 = values[1];
if (! (o1 is bool)) {
return o0;
}
bool toBeDisplayed = (bool) o1;
if (! toBeDisplayed) {
return 0.0;
}
if (! (o0 is double)) {
return 0;
}
return (double) o0;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
return new object[] { (double)value, Binding.DoNothing };
}
Ответ 8
Это работает для меня
Необходимо связать видимость как с заголовком, так и с содержимым
В этом случае это в конце, поэтому я не беспокоюсь о ширине
НО пользователь не получает привязку UI к reset ширине, поэтому, если вы установите ширину в ноль, она ушла
<GridViewColumn Width="60">
<GridViewColumnHeader HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch"
Visibility="{Binding Source={x:Static Application.Current}, Path=MyGabeLib.CurUser.IsInRoleSysAdmin, Converter={StaticResource bvc}}">
<TextBlock>WS<LineBreak/>Count</TextBlock>
</GridViewColumnHeader>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=WordScoreCount, StringFormat={}{0:N0}}" HorizontalAlignment="Right"
Visibility="{Binding Source={x:Static Application.Current}, Path=MyGabeLib.CurUser.IsInRoleSysAdmin, Converter={StaticResource bvc}}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
Ответ 9
У меня гораздо более простое решение, чем использование Attached Behavior.
Все, что вам нужно сделать, - привязать свойство Width к элементу GridViewColumn к логическому элементу на ViewModel. Затем создайте простой конвертер, такой как BooleanToWidthConverter, который принимает логическое значение и возвращает double, ноль, если его значение false, x, если оно истинно.
Надеюсь, это поможет и облегчит вашу жизнь.
XAML:
<GridViewColumn x:Name="MyHiddenGridViewColumn"
Width={Binding Path=IsColumnVisibleProperty, Converter={StaticResource BooleanToWidthConverter}}">
<!-- GridViewColumn.HeaderTemplate etc. goes here. -->
</GridViewColumn>
Преобразователь
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();
}
}