2009-04-08 1 views
29

У меня есть следующий объект в App.xamlWPF: Как скрыть GridViewColumn с помощью 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?

Любые идеи?

ответ

0

Я предлагаю использовать пользовательское свойство (или захват существующего) для родителя, а затем использовать пользовательский стиль в 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> 
+0

Я просто понял, что это только скрывает заголовок столбца, и это, вероятно, не то, что вы хотели сделать. Я не могу найти способ скрыть весь столбец только с помощью xaml, за исключением того, что вы делаете второй gridview. –

+3

Установка ширины GridViewColumn в 0 приведет к ее сглаживанию. –

+1

Я пробовал это, но на самом деле это не так. Вы все равно можете развернуть его мышью. –

5

Вы лучше всего, вероятно, чтобы создать пользовательский элемент управления унаследовав от класса 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» a DependencyProperty, чтобы использовать его как цель привязки.

4

Взятые из 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> 
+1

Ницца. Скрывает только заголовок, оставляя ячейки видимыми. –

+2

Не то, о чем попросил ОП, но это хорошо знать. (Лично я хотел бы сделать столбцы очень тонкими, так что по-прежнему можно изменять размеры столбцов). – Qwertie

17

На самом деле, я считаю, самым простым решением является с помощью вложенных свойств:

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> ... 
+1

моя реализация ожидает, что видимость столбца будет статичной для нагрузки - если вы ожидаете, что это изменится, однако, возможно, вам придется исправить UpdateListView(), чтобы сделать что-то еще, чтобы скрыть и показать столбец (Width = 0). –

+0

Это лучшее решение, которое я нашел до сих пор, и мне удалось заставить его работать с динамическим изменением свойства Visibile. См. Мой ответ. Это особенно полезно, если вы хотите скрыть по умолчанию, а затем, если необходимо, показать столбец. – surfen

+0

Это решение не работает для меня. Когда я отлаживался, я узнал, что метод UpdateListView вызывается первым, а значение свойства IsVisible появляется позже. Думаю, это причина в моем случае, но я не знаю почему? Может ли кто-нибудь объяснить, почему это может произойти? – Pegieo

1

Этот это мой код, он очень хорошо работает в моем проекте. если вам не нравится добавлять внешний код.

/// <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; 
         } 
        } 
       } 

      } 

     } 
    } 
12

Основано на ответе Бен Макмиллана, но поддерживает динамическое изменение видимого свойства. Я упростил его решение, удалив свойство 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]; 
     } 
    } 
} 
+1

Работает как очарование. Спасибо ! – Olwaro

+0

Блестящий! Спасибо –

+0

Будет ли это не утечка памяти? Вы сохраняете сам элемент управления в статическом словаре ... – Rashack

0

In a small utility I wrote, у меня есть представление списка, где пользователь может скрыть/показать некоторые столбцы. В столбцах нет свойства видимости, поэтому я решил установить ширину скрытых колонок равными нулю. Не идеально, так как пользователь может изменить их размер и сделать их видимыми снова.

В любом случае, чтобы сделать это, я использовал:

<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 }; 
} 
0

Это работает для меня
нужно связать видимостью как на заголовок и содержание
В данном случае это в конце, так что я не беспокоиться о Ширина
, но пользователь не получает крючок пользовательского интерфейса, чтобы сбросить ширину, так что если вы установите ширину до нуля он ушел

<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> 
0

у меня есть гораздо более простое решение, чем использование прикрепленным поведения.

Все, что вам нужно сделать, это привязать свойство 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(); 
     } 
    }