这几天做项目,需要做个listview满足能够动态显示或隐藏某些列,由于自己是菜鸟水平,查了两天资料也没有想出解决办法。就在我山穷水尽的时候看到了Mgen的一篇博客,给了我很大启发,所以我也决定把自己做的一些东西给大家说说,希望能帮助像我一样的菜鸟!
我读了Mgen的博文(http://www.cnblogs.com/mgen/archive/2011/07/24/2115458.html),给我很大启发,但也发现有些缺陷。我感觉的缺陷列举如下:
1、控制隐藏显示的逻辑关系有问题,搞不好会抛异常。
2、你设置管理控制显隐的控件只能是继承于itemcontrol的控件,有一定的局限性(比如说我想做一组button按钮,每个button控制一列话,它就不能用了)
下面,我贴出自己的代码,然后分析我是怎样解决这些问题的。

1 <Window x:Class="mgen_autocolumns.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:loc="clr-namespace:mgen_autocolumns" 5 Title="Mgen" Height="350" Width="525"> 6 <DockPanel> 7 <!-- 已经有的ListView --> 8 <ListView Name="list" DockPanel.Dock="Top" > 9 <ListView.View> 10 <GridView loc:GridViewUtility.ColumnObjectCollection="{Binding Path=ColumnCollection}"> 11 <GridViewColumn Header="姓名" 12 Width="100" 13 DisplayMemberBinding="{Binding Name}" /> 14 <GridViewColumn Header="年龄" 15 Width="50" 16 DisplayMemberBinding="{Binding Age}" /> 17 <GridViewColumn Header="分数" 18 Width="100"> 19 <GridViewColumn.CellTemplate> 20 <DataTemplate> 21 <ProgressBar Width="80" Height="10" Maximum="100" Value="{Binding Score}" /> 22 </DataTemplate> 23 </GridViewColumn.CellTemplate> 24 </GridViewColumn> 25 </GridView> 26 </ListView.View> 27 </ListView> 28 29 <!-- 列管理代码 --> 30 <!-- loc命名空间是ColumnObject的CLR命名空间 --> 31 <ListBox ItemsSource="{Binding Path=ColumnCollection.GViewAllCollection}"> 32 <!--<ListBox.ItemContainerStyle> 33 <Style TargetType="ListBoxItem"> 34 <Setter Property="Focusable" Value="False" /> 35 </Style> 36 </ListBox.ItemContainerStyle>--> 37 <ListBox.ItemTemplate> 38 <DataTemplate> 39 <CheckBox IsChecked="{Binding Path=IsVisable}" 40 Content="{Binding Path=Header}" 41 Margin="2"/> 42 </DataTemplate> 43 </ListBox.ItemTemplate> 44 </ListBox> 45 </DockPanel> 46 </Window>

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; namespace mgen_autocolumns { public class GridViewUtility : GridView { #region 附加属性 public static readonly DependencyProperty ColumnObjectCollectionProperty = DependencyProperty.RegisterAttached("ColumnObjectCollection", typeof(ColumnObjectCollections), typeof(GridView), new PropertyMetadata(GridViewUtility.OnColumnObjectCollectionChanged)); static void OnColumnObjectCollectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ColumnObjectCollections col = e.NewValue as ColumnObjectCollections; if (col != null) { col.GViewCollection = ((GridView)d).Columns; int index = 0; col.GViewAllCollection = new List<ColumnObject>(); foreach (GridViewColumn gc in col.GViewCollection) { col.GViewAllCollection.Add(new ColumnObject(index, true,gc, col)); index++; } } } public static ColumnObjectCollections GetColumnObjectCollection(GridView gridview) { return (ColumnObjectCollections)gridview.GetValue(ColumnObjectCollectionProperty); } public static void SetColumnObjectCollection(GridView gridew, ColumnObjectCollections collection) { gridew.SetValue(ColumnObjectCollectionProperty, collection); } #endregion } public class ColumnObjectCollections { public GridViewColumnCollection GViewCollection { get; set; } public List<ColumnObject> GViewAllCollection { get; set; } public void SetColumnVisable(int index, bool isVisable) { if (index >= 0 && index < GViewAllCollection.Count) { GViewAllCollection[index].IsVisable = isVisable; } } public bool IsColumnVisable(int index) { if (index < 0 || index >= GViewAllCollection.Count) { return false; } return GViewAllCollection[index].IsVisable; } } public class ColumnObject { private int index; private ColumnObjectCollections col; private GridViewColumn column; private bool isVisable; public bool IsVisable { get { return isVisable; } set { isVisable = value; SetVisable(isVisable); } } public string Header { get { return this.column.Header.ToString(); } } public ColumnObject(int index, bool isVisable,GridViewColumn column, ColumnObjectCollections col) { this.index = index; this.IsVisable = true; this.col = col; this.column = column; } private void SetVisable(bool isVisable) { if (isVisable) { if (!this.IsVisable) { int index = this.index; this.col.GViewAllCollection[index].isVisable = true; for (int i = index + 1; i < this.col.GViewAllCollection.Count; i++) { if (this.col.GViewAllCollection[i].isVisable) { index = this.col.GViewAllCollection[i].index - 1; break; } } this.col.GViewCollection.Insert(index, this.column); } } else { this.col.GViewCollection.Remove(this.column); } } } }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace mgen_autocolumns 7 { 8 public class Person 9 { 10 public ColumnObjectCollections ColumnCollection 11 { 12 get; 13 set; 14 } 15 public Person() 16 { 17 ColumnCollection = new ColumnObjectCollections(); 18 } 19 public Person(string name, int age, int score) 20 { 21 Name = name; 22 Age = age; 23 Score = score; 24 } 25 public string Name { get; set; } 26 public int Age { get; set; } 27 public int Score { get; set; } 28 29 public static Person[] Get() 30 { 31 return new Person[] 32 { 33 new Person("Zhang", 14, 91), 34 new Person("Mgen",21,77), 35 new Person("Lee",40,93), 36 new Person("123",32,35), 37 new Person("Gao",22,71), 38 new Person("Sun",9,21), 39 new Person("David",71,12) 40 }; 41 } 42 } 43 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input; 10 using System.Windows.Media; 11 using System.Windows.Media.Imaging; 12 using System.Windows.Navigation; 13 using System.Windows.Shapes; 14 15 namespace mgen_autocolumns 16 { 17 /// <summary> 18 /// Interaction logic for MainWindow.xaml 19 /// </summary> 20 public partial class MainWindow : Window 21 { 22 public MainWindow() 23 { 24 this.DataContext = new Person(); 25 InitializeComponent(); 26 list.ItemsSource = Person.Get(); 27 28 } 29 30 } 31 }