这几天做项目,需要做个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"XAML
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;View Code
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;Person Code
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;MainWindow Code
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 }