2009-04-08 14 views
29

tôi có các đối tượng sau đây trong App.xamlWPF: Làm cách nào để ẩn GridViewColumn bằng XAML?

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

... more code ... 

Và tôi sử dụng xem lưới này ở nhiều nơi. Ví dụ:

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

Trong một trong những tập quán (như detailList ở trên), tôi muốn ẩn cột tạo, có thể sử dụng XAML?

Bất kỳ ý tưởng nào?

Trả lời

0

Tôi khuyên bạn nên sử dụng thuộc tính tùy chỉnh (hoặc chiếm đoạt thuộc tính hiện có) trên trang gốc và sau đó sử dụng kiểu tùy chỉnh trên Gridviewcolumnheader để tham chiếu thuộc tính tổ tiên đó. Như thế này:

<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

Tôi chỉ nhận ra rằng đây chỉ có thể giấu các tiêu đề cột, và điều đó có lẽ không phải những gì bạn muốn làm. Tôi không thể tìm thấy bất kỳ cách nào để ẩn toàn bộ cột chỉ với xaml ngoại trừ việc tạo một khung nhìn thứ hai. –

+3

Đặt chiều rộng của GridViewColumn thành 0 sẽ có hiệu quả ẩn nó. –

+1

Tôi đã thử điều đó, nhưng nó không thực sự biến mất. Bạn vẫn có thể mở rộng bằng chuột. –

5

Bạn tốt nhất đặt cược có lẽ là để tạo ra một điều khiển tùy chỉnh bởi kế thừa từ các lớpGridView, thêm các cột cần thiết, và phơi bày một tài sản có ý nghĩa để hiển thị/ẩn một cột cụ thể. lớp GridView tùy chỉnh bạn có thể trông như thế này:

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

    } 
} 

Sau đó, bạn chỉ có thể thiết lập rằng tài sản từ XAML như trong ví dụ này:

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

Tùy chọn, bạn có thể làm cho 'CustomGridView.ShowOptionalColumn' a DependencyProperty để có thể sử dụng nó làm mục tiêu ràng buộc.

4

Taken từ 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

Tuyệt. Chỉ ẩn tiêu đề, để lại các ô hiển thị. –

+2

Không phải những gì OP yêu cầu, nhưng tốt để biết. (Cá nhân tôi muốn làm cho các cột thực sự mỏng nên vẫn có thể thay đổi kích thước cột) – Qwertie

17

Thực ra, tôi tìm ra giải pháp đơn giản nhất là qua tài sản gắn liền:

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

Sau đó, nó có thể được sử dụng như vậy:

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

triển khai của tôi mong đợi khả năng hiển thị của cột là tĩnh cho tải - nếu bạn mong đợi điều này thay đổi, tuy nhiên, bạn có thể cần sửa UpdateListView() để làm một cái gì đó khác để ẩn và hiển thị cột (Width = 0). –

+0

Đây là giải pháp tốt nhất tôi đã tìm thấy cho đến nay, và tôi đã quản lý để làm cho nó hoạt động với sự thay đổi năng động của thuộc tính Visibile. Xem câu trả lời của tôi. Nó đặc biệt hữu ích nếu bạn muốn ẩn theo mặc định và sau đó hiển thị cột nếu cần. – surfen

+0

Giải pháp này không phù hợp với tôi. Khi tôi gỡ lỗi, tôi phát hiện ra rằng phương thức UpdateListView được gọi là giá trị thuộc tính đầu tiên và IsVisible được nhận sau đó. Tôi đoán đây là lý do trong trường hợp của tôi nhưng tôi không biết tại sao? Ai có thể giải thích tại sao nó có thể xảy ra? – Pegieo

1

này là mã của tôi, nó hoạt động rất tốt trong dự án của tôi. nếu bạn không muốn thêm một số mã bên ngoài.

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

Dựa trên câu trả lời của Ben McMillan, nhưng hỗ trợ thay đổi động của tài sản hiển thị. Tôi đã đơn giản hóa giải pháp của mình hơn nữa bằng cách xóa thuộc tính 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

Hoạt động như một sự quyến rũ. Cảm ơn bạn ! – Olwaro

+0

Rực rỡ! Cảm ơn –

+0

Liệu bộ lọc này có bị rò rỉ không? Bạn đang lưu trữ bản thân kiểm soát trong một từ điển tĩnh ... – Rashack

0

In a small utility I wrote, tôi có chế độ xem danh sách nơi người dùng có thể ẩn/hiển thị một số cột. Không có thuộc tính Visibility trên các cột, vì vậy tôi quyết định thiết lập chiều rộng cột ẩn thành 0. Không lý tưởng vì người dùng vẫn có thể đổi kích thước chúng và hiển thị lại chúng.

Dù sao, để làm điều này, tôi đã sử dụng:

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

IsThreadIdShown được ràng buộc với một hộp kiểm trên thanh công cụ. Và công cụ chuyển đổi đa giá trị là:

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

này làm việc cho tôi
Cần để ràng buộc Visibility trên cả tiêu đề và nội dung
Trong trường hợp này nó là ở cuối vì vậy tôi không lo lắng về width
NHƯNG người dùng không có được một cái móc UI để thiết lập lại độ rộng vì vậy nếu bạn thiết lập độ rộng về không nó đã biến mất

<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

tôi có một giải pháp đơn giản hơn nhiều so với sử dụng một hành vi đính kèm.

Tất cả những gì bạn phải làm là liên kết Thuộc tính chiều rộng của GridViewColumn với boolean trên ViewModel của bạn. Sau đó, tạo một Trình chuyển đổi đơn giản như BooleanToWidthConverter lấy một boolean và trả về một giá trị gấp đôi, nếu nó là false, x width nếu đúng.

Tôi hy vọng điều này sẽ giúp và giúp cuộc sống của bạn dễ dàng hơn.

XAML:

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

Chuyển đổi:

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