using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Xml;
namespace WpfApp1.Helper
{
public class ColumnHelper
{
string filename;
XmlDocument xmlDoc = new XmlDocument();
DataGrid dgPerson;
/// <summary>
/// 用指定的DataGrid和文件名初始化ColumnHelper类的新实例
/// </summary>
/// <param name="dgPerson"></param>
public ColumnHelper(DataGrid dgPerson, string filename)
{
// TODO: Complete member initialization
this.dgPerson = dgPerson;
this.filename = filename;
}
/// <summary>
/// 添加右键菜单中的CheckBox
/// </summary>
/// <param name="content">CheckBox显示的名字</param>
/// <param name="source">绑定的列名</param>
public void addCheckbox()
{
ContextMenu cm = new ContextMenu();
for (int i = 0; i < dgPerson.Columns.Count; i++)
{
CheckBox cb = new CheckBox();
cb.Content = dgPerson.Columns[i].Header.ToString();
bindColumnAndCheckbox(dgPerson.Columns[i], cb);
cm.Items.Add(cb);
}
dgPerson.ContextMenu = cm;
}
/// <summary>
/// 将DataGrid中的列的Visibility属性和CheckBox的IsCheck属性绑定
/// </summary>
/// <param name="column">绑定的列名</param>
/// <param name="checkbox">显示的CheckBox</param>
public void bindColumnAndCheckbox(object column, CheckBox checkbox)
{
Binding binding = new Binding("Visibility");
binding.Source = column;
binding.Converter = new MyConverter(); // 设定Converter
checkbox.SetBinding(CheckBox.IsCheckedProperty, binding);
}
/// <summary>
/// 读取XML文件中的配置信息
/// </summary>
/// <param name="filename">XML文件路径</param>
public void readXML()
{
try
{
xmlDoc.Load(filename);
XmlNodeList list = xmlDoc.GetElementsByTagName("*");
XmlElement element;
for (int i = 1; i < list.Count; i++)
{
element = (XmlElement)list.Item(i);
string str = element.InnerText.ToString();
dgPerson.Columns[i - 1].Visibility = (Visibility)Enum.Parse(typeof(Visibility), str, true);
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 将配置信息写入XML文件中
/// </summary>
/// <param name="filename">XML文件路径</param>
public void writeXML()
{
try
{
XmlNode xmlNode = xmlDoc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
XmlNode myNode = xmlDoc.CreateNode(XmlNodeType.Element, "appSetting", "");
if (!System.IO.File.Exists(filename))
{
xmlDoc.AppendChild(xmlNode);
xmlDoc.AppendChild(myNode);
for (int i = 0; i < dgPerson.Columns.Count; i++)
{
string strRoot = dgPerson.Columns[i].Header.ToString();
string strText = dgPerson.Columns[i].Visibility.ToString();
XmlElement xmlelem = xmlDoc.CreateElement("", strRoot, "");
xmlelem.InnerText = strText;
myNode.AppendChild(xmlelem);
}
xmlDoc.Save(filename);
}
else
{
xmlDoc.Load(filename);
XmlNodeList list = xmlDoc.GetElementsByTagName("*");
XmlElement element;
for (int i = 1; i < list.Count; i++)
{
element = (XmlElement)list.Item(i);
element.InnerText = dgPerson.Columns[i - 1].Visibility.ToString();
}
xmlDoc.Save(filename);
}
}
catch (Exception ex)
{
throw ex;
}
}
}
/// <summary>
/// 转换器。功能:使CheckBox的IsChecked属性和DataGrid控件中的列的Visibility属性可以关联。
/// </summary>
[ValueConversion(typeof(Enum), typeof(bool?))]
public class MyConverter : IValueConverter
{
/// <summary>
/// 将DataGrid列的Visibility属性转换为bool型,方便CheckBox的IsChecked属性赋值
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string str = System.Convert.ToString(value);
if (str.Equals("Visible"))
return true;
else
return false;
}
/// <summary>
/// 将CheckBox的IsChecked属性的bool值转换成Visibility属性,方便DataGrid列属性赋值
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool b = System.Convert.ToBoolean(value);
if (b.Equals(true))
{
return (Visibility)Enum.Parse(typeof(Visibility), "Visible", true);
}
else
return (Visibility)Enum.Parse(typeof(Visibility), "Hidden", true);
}
}
}
xaml
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<DataGrid x:Name="test" PreviewMouseRightButtonDown="Test_PreviewMouseRightButtonDown">
<DataGrid.Columns>
<DataGridTextColumn Header="ID"/>
<DataGridTextColumn Header="Name"/>
<DataGridTextColumn Header="Age"/>
<DataGridTextColumn Header="Address"/>
<DataGridTextColumn Header="School"/>
<DataGridTextColumn Header="Phone"/>
<DataGridTextColumn Header="Count"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
mainwindows.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApp1.Helper;
namespace WpfApp1
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Test_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
Point Pmouser = e.GetPosition((ItemsControl)sender);
if (Pmouser.Y <= 30)
{
new ColumnHelper(this.test, "test.xml").addCheckbox();
}
}
}
}
效果图
在使用的时候,只要实例化一下这个类就可以了(这里记得要把需要该功能的DataGrid作为参数传入,由于我这里使用的是XML文件来保存用户的自定义列布局,所以还要将保存
XML的文件名也作为参数传入)。在页面加载时读取XML文件里的信息,以此判断哪些列显示,哪些列不显示。第一次运行时这个XML文件肯定不存在,所以要加上判断条件,不存
在就不管了(第一次运行肯定所有列都要显示出来),以后运行的话文件肯定已经存在了,这是再进行读取XML操作就好。页面关闭的时候调用写入XML的方法。 最终的运行效果
就是当在DataGrid控件上点击右键的时候,弹出和DataGrid中的列一一对应的CheckBox,并且CheckBox的IsChecked属性和DataGrid列的Visibility属性已经绑定。