2009-04-08 15 views
29

Tengo el siguiente objeto en App.xamlWPF: ¿Cómo ocultar GridViewColumn usando XAML?

<Application.Resources> 
     <ResourceDictionary> 
      <GridView x:Key="myGridView" x:Shared="false"> 
          <GridViewColumn Header="Created" DisplayMemberBinding="{Binding Path=Created}"/> 

... more code ... 

y utilizo este punto de vista de cuadrícula en múltiples lugares. Ejemplo:

<ListView x:Name="detailList" View="{StaticResource myGridView}" ...> 

En uno de los usos (como DetailList arriba), me gustaría para ocultar el Creado columna, posiblemente usando XAML?

¿Alguna idea?

Respuesta

0

Sugeriría utilizar una propiedad personalizada (o secuestro de una existente) en el elemento primario y luego usar un estilo personalizado en gridviewcolumnheader para hacer referencia a esa propiedad ancestro. De esta manera:

<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

Me acabo de dar cuenta que esto sólo oculta el encabezado de la columna, y que probablemente no es lo que quería hacer. No puedo encontrar ninguna forma de ocultar toda la columna con solo xaml excepto hacer una segunda vista de cuadrícula. –

+3

Establecer un ancho de GridViewColumn a 0 lo ocultará efectivamente. –

+1

Lo intenté, pero en realidad no se ha ido entonces. Aún puedes expandirlo con el mouse. –

5

Es mejor apuesta es, probablemente, para crear un control encargo heredando de la claseGridView, añadiendo las columnas necesarias, y exponer una propiedad significativa para mostrar/ocultar una columna en particular. Su clase GridView personalizada podría tener este aspecto:

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

    } 
} 

continuación, puede establecer simplemente que la propiedad de XAML como en este ejemplo:

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

Opcionalmente, se puede hacer que el 'CustomGridView.ShowOptionalColumn' a DependencyProperty para poder utilizarlo como un objetivo vinculante.

4

Tomado de 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

Agradable. Oculta solo el encabezado, dejando las celdas visibles. –

+2

No es lo que pidió el OP, pero es bueno saberlo. (Personalmente, me gustaría que las columnas sean muy finas para que aún sea posible cambiar el tamaño de las columnas) – Qwertie

17

En realidad, me parece la solución más fácil es a través de las propiedades asociadas:

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

A continuación, se puede utilizar como tal:

<ListView foo:GridViewColumnVisibilityManager.Enabled="True"> 
... 
<GridViewColumn Header="Status" foo:GridViewColumnVisibilityManager.IsVisible="{Binding ShowStatusColumn}"> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> ... 
+1

mi implementación espera que la visibilidad de una columna sea estática para una carga; sin embargo, si espera que esto cambie, es posible que deba corregirlo UpdateListView() para hacer algo más para ocultar y mostrar la columna (Ancho = 0). –

+0

Esta es la mejor solución que he encontrado hasta ahora, y he logrado que funcione con el cambio dinámico de la propiedad Visibile. Ver mi respuesta Es particularmente útil si desea ocultar por defecto y luego mostrar la columna si es necesario. – surfen

+0

Esta solución no funciona para mí. Cuando depuré, descubrí que el método UpdateListView se llama primero y el valor de la propiedad IsVisible se obtiene después. Supongo que esta es una razón en mi caso, pero no sé por qué? ¿Alguien podría explicar por qué puede suceder? – Pegieo

1

Este es mi código, funciona muy bien en mi proyecto. si no te gusta agregar algún código externo.

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

Según la respuesta de Ben McMillan, pero admite el cambio dinámico de la propiedad visible. He simplificado aún más su solución al eliminar la propiedad 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

Funciona como un encanto. Gracias ! – Olwaro

+0

¡Brillante! Gracias –

+0

¿Esto no perderá memoria? Está almacenando el control en un diccionario estático ... – Rashack

0

In a small utility I wrote, tengo una vista de lista en el que el usuario puede ocultar/mostrar algunas columnas. No hay propiedad de Visibilidad en las columnas, por lo que decidí establecer el ancho de las columnas ocultas a cero. No es ideal, ya que el usuario aún puede redimensionarlos y volverlos visibles.

De todos modos, para hacer esto, he utilizado:

<GridViewColumn.Width> 
    <MultiBinding Converter="{StaticResource WidthConverter}" Mode="TwoWay"> 
     <Binding Path="ThreadIdColumnWidth" Mode="TwoWay" /> 
     <Binding Path="IsThreadIdShown" /> 
    </MultiBinding> 
</GridViewColumn.Width> 

IsThreadIdShown está obligado a una casilla de verificación en la barra de herramientas. y el convertidor de valores múltiples es:

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

Esto funciona para mí
necesitan de obligar a la visibilidad tanto en la cabecera y el contenido
En este caso, es al final, así que no se preocupe aproximadamente el ancho
pero el usuario no recibe un gancho de interfaz de usuario para restablecer el ancho de manera que si establece el ancho a cero que se ha ido

<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

tengo una solución mucho más simple que el uso de un comportamiento adjunto.

Todo lo que tiene que hacer es vincular la propiedad Ancho de la GridViewColumn a un valor booleano en su ViewModel. A continuación, cree un convertidor simple como BooleanToWidthConverter que toma un booleano y devuelve un doble, cero si es falso, x ancho si es verdadero.

Espero que esto ayude y te haga la vida más fácil.

XAML:

<GridViewColumn x:Name="MyHiddenGridViewColumn" 
       Width={Binding Path=IsColumnVisibleProperty, Converter={StaticResource BooleanToWidthConverter}}"> 
    <!-- GridViewColumn.HeaderTemplate etc. goes here. --> 
</GridViewColumn> 

Convertidor:

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(); 
     } 
    } 
Cuestiones relacionadas