2009-04-08 14 views
29

Ich habe folgendes Objekt in App.xamlWPF: Wie GridViewColumn mit XAML ausblenden?

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

... more code ... 

Und ich diese Rasteransicht an mehreren Stellen. Beispiel:

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

In einem der Nutzungen (wie oben Detaillist), würde Ich mag die Erstellt Spalte verbergen, möglicherweise XAML?

Irgendwelche Ideen?

Antwort

0

Ich würde vorschlagen, eine benutzerdefinierte Eigenschaft (oder Hijacking eine vorhandene) für das übergeordnete Element und dann einen benutzerdefinierten Stil auf dem Gridviewcolumnheader verwenden, um diese Vorfahreneigenschaft zu verweisen. Wie folgt aus:

<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

Ich habe erkannt, dass dies nur auf den Spaltenkopf versteckt, und das ist wahrscheinlich nicht das, was Sie tun wollte. Ich finde keine Möglichkeit, die ganze Spalte mit nur Xaml zu verstecken, außer nur eine zweite Gridview zu machen. –

+3

Wenn Sie die Breite einer GridViewColumn auf 0 setzen, wird sie effektiv ausgeblendet. –

+1

Ich habe das versucht, aber es ist dann nicht wirklich weg. Sie können es immer noch mit der Maus erweitern. –

5

Sie beste Wette ist wahrscheinlich eine individuelle Steuerung durch Erben von der Grid Klasse zu erstellen, das Hinzufügen der gewünschten Spalten und eine sinnvolle Eigenschaft Aussetzen einer bestimmten Spalte ein-/auszublenden. Ihre benutzerdefinierte Gridview Klasse könnte wie folgt aussehen:

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

    } 
} 

Dann können Sie einfach festlegen, dass das Eigentum von XAML wie in diesem Beispiel:

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

Optional könnten Sie die ‚CustomGridView.ShowOptionalColumn‘ machen a DependencyProperty, um es als verbindliches Ziel verwenden zu können.

4

Entnommen 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

Schön. Blendet nur den Header aus und lässt Zellen sichtbar. –

+2

Nicht was der OP verlangt, aber gut zu wissen. (Persönlich möchte ich die Spalten wirklich dünn machen, so dass es immer noch möglich ist, Spalten in der Größe anzupassen) – Qwertie

17

Eigentlich finde ich die einfachste Lösung über angefügten Eigenschaften: Dieses

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

meine Implementierung erwartet, dass die Sichtbarkeit einer Spalte für eine Ladung statisch ist - wenn Sie erwarten, dass sich dies ändert, müssen Sie möglicherweise beheben UpdateListView(), um etwas anderes zu tun, um die Spalte auszublenden und anzuzeigen (Width = 0). –

+0

Dies ist die beste Lösung, die ich bisher gefunden habe, und ich habe es geschafft, es mit der dynamischen Änderung der Visible-Eigenschaft zum Laufen zu bringen. Siehe meine Antwort. Es ist besonders nützlich, wenn Sie standardmäßig ausblenden möchten und später die Spalte ggf. anzeigen. – surfen

+0

Diese Lösung funktioniert nicht für mich. Als ich debuggte, fand ich heraus, dass die Methode UpdateListView zuerst aufgerufen wird und danach der IsVisible-Eigenschaftswert get. Ich denke, das ist der Grund in meinem Fall, aber ich weiß nicht warum? Kann jemand erklären, warum es passieren kann? – Pegieo

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

Dann kann es als so verwendet werden, ist mein Code, es funktioniert sehr gut in meinem Projekt. wenn Sie keinen externen Code hinzufügen möchten.

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

Basiert auf Ben McMillans Antwort, unterstützt aber dynamische Änderung der sichtbaren Eigenschaft. Ich habe seine Lösung weiter vereinfacht, indem ich die IsEnabled-Eigenschaft entfernt habe.

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

Funktioniert wie ein Charme. Vielen Dank ! – Olwaro

+0

Brilliant! Danke –

+0

Wird dies Speicher nicht verlieren? Sie speichern das Steuerelement selbst in einem statischen Wörterbuch ... – Rashack

0

In a small utility I wrote, Ich habe eine Listenansicht, wo der Benutzer einige Spalten verstecken/anzeigen kann. Da in den Spalten keine Sichtbarkeitseigenschaft vorhanden ist, entschied ich, die Breite der ausgeblendeten Spalten auf Null zu setzen. Nicht ideal, da der Benutzer sie immer noch in der Größe ändern und wieder sichtbar machen kann.

Wie auch immer, dies zu tun, habe ich:

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

IsThreadIdShown ist gebunden an ein Kontrollkästchen auf der Symbolleiste. Und der Mehrwert-Wandler:

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

Dies funktioniert für mich
möchten die Sichtbarkeit sowohl auf dem Header und den Inhalt
In diesem Fall binden sie am Ende ist, damit ich keine Sorgen über die Breite
aber der Benutzer keine UI Haken bekommt die Breite zurückgesetzt, so wenn Sie die Breite auf Null gesetzt es

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

ich habe eine viel einfachere Lösung als ein angebaute Verhalten verwenden.

Alles, was Sie tun müssen, ist die Width-Eigenschaft der GridViewColumn mit einem boolean auf Ihrem ViewModel zu binden. Dann erstellen Sie einen einfachen Converter wie BooleanToWidthConverter, der einen booleschen Wert annimmt und ein Double zurückgibt, Null, wenn es falsch ist, x Breite, wenn es wahr ist.

Ich hoffe, das hilft und macht Ihr Leben leichter.

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