wpf datagrid 给表头添加右键,以及实现datagrid的数据筛选

https://github.com/xdqt/wpfdatagrid-filter-columnshow.git

在这里插入图片描述
ColumnHelper是给列头添加右键,动态设置列显示

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.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using System.Xml;

namespace WpfApp.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);
            }

            //只给表头设置contextmenu

            var columnHeadersPresenter = this.dgPerson.SafeFindDescendant<DataGridColumnHeadersPresenter>(ip => ip.Name == "PART_ColumnHeadersPresenter");
            if (columnHeadersPresenter != null)
            {
                columnHeadersPresenter.ContextMenu = cm;
            }



            //for (int i = 0; i < dgPerson.Columns.Count; i++)
            //{
            //    var tb = new TextBlock { Text = dgPerson.Columns[i] .Header.ToString()};
            //    tb.ContextMenu = cm;
            //    dgPerson.Columns[i].Header = tb;
            //}
            //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;
            }
        }


    }



    public static class Visual_ExtensionMethods
    {
        /// <summary>
        /// Retrieves the first Descendant of the currren Visual in the VisualTree matching the given predicate
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="this">The current Visual.</param>
        /// <param name="predicate">An optional predicate that the descendant have to satisfy.</param>
        /// <returns></returns>
        public static T SafeFindDescendant<T>(this Visual @this, Predicate<T> predicate = null) where T : Visual
        {
            T result = null;
            if (@this == null)
            {
                return null;
            }

            // iterate on VisualTree children thanks to VisualTreeHelper
            int childrenCount = VisualTreeHelper.GetChildrenCount(@this);
            for (int i = 0; i < childrenCount; i++)
            {
                var currentChild = VisualTreeHelper.GetChild(@this, i);

                var typedChild = currentChild as T;
                if (typedChild == null)
                {
                    // recursive search
                    result = ((Visual)currentChild).SafeFindDescendant<T>(predicate);
                    if (result != null)
                    {
                        break;
                    }
                }
                else
                {
                    if (predicate == null || predicate(typedChild))
                    {
                        result = typedChild;
                        break;
                    }
                }
            }

            return result;
        }
    }
    /// <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);
        }
    }
}


usercontrol.xaml

<UserControl x:Class="WpfApp.UserControls.UserControls"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:con="clr-namespace:WpfApp"
             mc:Ignorable="d" 
             x:Name="main"
             >
    <UserControl.Resources>
        <con:Visible x:Key="visible" />
        <con:Images x:Key="image"/>
    </UserControl.Resources>
    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition Height="3*"/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Orientation="Horizontal">
            <TextBlock Text="筛选: "/>
            <TextBox  Height="20" Width="100" x:Name="search" TextChanged="TextBox_TextChanged"/>
        </StackPanel>
        
        <DataGrid x:Name="test"
                  Margin="0,5"
                  PreviewMouseRightButtonDown="Test_PreviewMouseRightButtonDown"
                  Grid.Row="1"
                  CanUserAddRows="False"
                  SelectionMode="Single" 
                      CanUserDeleteRows="False"
                      CanUserSortColumns="False"
                      CanUserReorderColumns ="True"    
                      CanUserResizeColumns="True"
                  ItemsSource="{Binding datas}"
                  AutoGenerateColumns="False"
                  SelectedItem="{Binding Selected}">

            <DataGrid.Columns>
                
                <DataGridTextColumn Header="id" x:Name="id" Binding="{Binding ID}" Width="0.2*">

                </DataGridTextColumn>
                <DataGridTextColumn  Header="age" x:Name="age" Binding="{Binding Age}" Width="0.2*">

                </DataGridTextColumn>
                <DataGridTextColumn Header="name" x:Name="name" Binding="{Binding Name}" Width="*">
                    
                </DataGridTextColumn>
            </DataGrid.Columns>
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow" >
                    <Setter Property="Height" Value="30" />
                    <Setter Property="HorizontalAlignment" Value="Center"/>
                    <Setter Property="VerticalAlignment" Value="Center"/>
                    <Style.Triggers>
                        <Trigger Property="ItemsControl.AlternationIndex" 
                                 Value="0">
                            <Setter Property="Foreground" Value="Red" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.RowStyle>
            
            <DataGrid.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="合并账号" >
                        <MenuItem.Icon>
                            <StackPanel>
                                <Image Source="pack://application:,,,/ICON/icon.png"></Image>
                            </StackPanel>
                        </MenuItem.Icon>
                        <MenuItem Header="测试" Visibility="{Binding  RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.SelectedItem,Converter={StaticResource visible}}">

                        </MenuItem>
                        <MenuItem Header="测试1" />
                    </MenuItem>
                </ContextMenu>
            </DataGrid.ContextMenu>
        </DataGrid>
    </Grid>
</UserControl>

usercontrol.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 WpfApp.Helper;

namespace WpfApp.UserControls
{
    /// <summary>
    /// UserControl.xaml 的交互逻辑
    /// </summary>
    public partial class UserControls : UserControl
    {
        public UserControls()
        {
            InitializeComponent();
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            var cvs = CollectionViewSource.GetDefaultView(test.ItemsSource);
            if (cvs != null && cvs.CanFilter)
            {
                cvs.Filter = OnFilterApplied;
            }

            
        }


        private bool OnFilterApplied(object obj)
        {
            if (obj is Datas)
            {
                //文本加空格 为确定搜索
                var text = search.Text.ToLower();
                if (text.Length > 0 && text.Substring(text.Length - 1, 1) == " ")
                {
                    text = text.TrimEnd();

                    return (obj as Datas).Name.ToLower().Equals(text); //车号
                  

                }
                else
                {
                    return (obj as Datas).Name.ToLower().Contains(text);
                }

            }
            return false;
        }

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

        private void Test_Loaded(object sender, RoutedEventArgs e)
        {
            
            
        }
    }
}

UserModels.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp
{
    public class UserModels:INotifyPropertyChanged
    {
        public ObservableCollection<Datas> datas { get; set; }
        public Datas Selected
        {
            set { selected = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Selected")); }
            get { return selected; }
        }

        private Datas selected;
        public UserModels()
        {
            datas = new ObservableCollection<Datas>()
            {
                new Datas{ID=1,Age=80,Name="dalian"},
                 new Datas{ID=2,Age=81,Name="dalian1"},
                  new Datas{ID=3,Age=82,Name="dalian2"},
                   new Datas{ID=4,Age=83,Name="dalian3"},
                    new Datas{ID=5,Age=84,Name="dalian4"},
            };
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }


    public class Datas
    {
        public int ID { get; set; }


        public int Age { get; set; }


        public string Name { get; set; }

        public override string ToString()
        {
            return this.Name;
        }
    }
}

ValueCon.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media.Imaging;

namespace WpfApp
{
    public class Visible : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Datas dd = value as Datas;
            if (dd is null)
            {
                return  Visibility.Collapsed; 
            }
            else
            {
                if (dd.Age >= 82)
                {
                    return Visibility.Visible; ;
                }
                else
                {
                    return Visibility.Collapsed;
                }
            }
            
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }




    public class Images : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Datas dd = value as Datas;
            if (dd is null)
            {
                return null;
            }
            else
            {
                if (dd.Age >= 82)
                {
                    string image = "ICON\\icon.png";
                    return  new BitmapImage(new Uri($"pack://application:,,,/{image}"));
                }
                else
                {
                    string image = "ICON\\icon.png";
                    return new BitmapImage(new Uri($"pack://application:,,,/{image}"));
                }
            }

        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

mainwindow.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;

namespace WpfApp
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.tests.DataContext = new UserModels();

        }
    }
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值