赞
踩
wpf的功能非常强大,很多控件都是原生的,但是要使用TreeView+DataGrid的组合,就需要我们自己去封装实现。
我们需要的效果如图所示:
这2个图都是第三方控件自带的,并且都是收费使用。
现在我们就用原生的控件进行封装一个。
本文源码效果如下,(搞了好几天,的确有难度,所以源码也收费,便宜,赚点辛苦费)
功能如上图所示, 目前基本上把常用的样式都实现了,购买源码后,可以自行修改样式。
首先说明一下,实现上面的效果,有3种方法
第一种:技术的选择是TreeView(也就是本文的演示)。
第二种:技术的选择是DataGrid。
WPF中使用DataGrid封装组合控件TreeView+DataGrid-粉丝专栏-CSDN博客
第三种:技术的选择是ListView。
WPF中使用ListView封装组合控件TreeView+DataGrid-粉丝专栏-CSDN博客
本文演示的是使用TreeView的实现。
1.首先建立一个wpf程序
2. 封装TreeGrid
- namespace TreeView.TreeDataGrid.Controls
- {
- //这里有一个骚操作,就是把引用放在里面
- using System;
- using System.Collections.Specialized;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Media;
-
- public class TreeGrid : TreeView
- {
- static TreeGrid()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeGrid), new FrameworkPropertyMetadata(typeof(TreeGrid)));
- }
-
- #region ColumnMappings DependencyProperty
- public string ColumnMappings
- {
- get { return (string)GetValue(ColumnMappingsProperty); }
- set { SetValue(ColumnMappingsProperty, value); }
- }
- public static readonly DependencyProperty ColumnMappingsProperty =
- DependencyProperty.Register("ColumnMappings", typeof(string), typeof(TreeGrid),
- new PropertyMetadata("", new PropertyChangedCallback(TreeGrid.OnColumnMappingsPropertyChanged)));
-
- private static void OnColumnMappingsPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
- {
- if (obj is TreeGrid)
- {
- (obj as TreeGrid).OnColumnMappingsValueChanged();
- }
- }
-
- protected void OnColumnMappingsValueChanged()
- {
- if (!string.IsNullOrEmpty(ColumnMappings))
- {
- ResetMappingColumns(ColumnMappings);
- }
- }
-
- private void ResetMappingColumns(string mapping)
- {
- GridViewColumnCollection items = new GridViewColumnCollection();
- var columns = mapping.Split(new char[] { ';', '|' }, StringSplitOptions.RemoveEmptyEntries);
- foreach (var c in columns)
- {
- var index = c.IndexOf(':');
- var title = "";
- var name = "";
- if (index > 0)
- {
- title = c.Substring(0, index);
- name = c.Substring(index + 1);
- }
- else
- {
- title = c;
- name = c;
- }
-
- DataTemplate temp = null;
- var res = this.FindTreeResource<DataTemplate>(name);
- if (res != null && res is DataTemplate template)
- {
- temp = template;
- }
- else
- {
- temp = new DataTemplate();
- FrameworkElementFactory element = null;
- if (items.Count == 0)
- {
- element = new FrameworkElementFactory(typeof(TreeItemContentControl));
- element.SetValue(ContentControl.ContentProperty, new Binding(name));
- }
- else
- {
- element = new FrameworkElementFactory(typeof(TreeGridCell));
- element.SetValue(ContentControl.ContentProperty, new Binding(name));
- }
- temp.VisualTree = element;
- }
-
- var col = new GridViewColumn
- {
- Width = 200,
- Header = title,
- CellTemplate = temp,
- };
- items.Add(col);
- }
- Columns = items;
- }
- #endregion
-
- #region Columns DependencyProperty
- public GridViewColumnCollection Columns
- {
- get { return (GridViewColumnCollection)GetValue(ColumnsProperty); }
- set { SetValue(ColumnsProperty, value); }
- }
- public static readonly DependencyProperty ColumnsProperty =
- DependencyProperty.Register("Columns", typeof(GridViewColumnCollection), typeof(TreeGrid),
- new PropertyMetadata(null, new PropertyChangedCallback(TreeGrid.OnColumnsPropertyChanged)));
-
- private static void OnColumnsPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
- {
- if (obj is TreeGrid)
- {
- (obj as TreeGrid).OnColumnsValueChanged();
- }
- }
-
- protected void OnColumnsValueChanged()
- {
-
- }
- #endregion
-
- #region RowHeight DependencyProperty
- public double RowHeight
- {
- get { return (double)GetValue(RowHeightProperty); }
- set { SetValue(RowHeightProperty, value); }
- }
- public static readonly DependencyProperty RowHeightProperty =
- DependencyProperty.Register("RowHeight", typeof(double), typeof(TreeGrid),
- new PropertyMetadata(30.0, new PropertyChangedCallback(TreeGrid.OnRowHeightPropertyChanged)));
-
- private static void OnRowHeightPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
- {
- if (obj is TreeGrid)
- {
- (obj as TreeGrid).OnRowHeightValueChanged();
- }
- }
-
- protected void OnRowHeightValueChanged()
- {
-
- }
- #endregion
-
- #region ShowCellBorder DependencyProperty
- public bool ShowCellBorder
- {
- get { return (bool)GetValue(ShowCellBorderProperty); }
- set { SetValue(ShowCellBorderProperty, value); }
- }
- public static readonly DependencyProperty ShowCellBorderProperty =
- DependencyProperty.Register("ShowCellBorder", typeof(bool), typeof(TreeGrid),
- new PropertyMetadata(false, new PropertyChangedCallback(TreeGrid.OnShowCellBorderPropertyChanged)));
-
- private static void OnShowCellBorderPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
- {
- if (obj is TreeGrid)
- {
- (obj as TreeGrid).OnShowCellBorderValueChanged();
- }
- }
-
- protected void OnShowCellBorderValueChanged()
- {
-
- }
- #endregion
-
- #region IconStroke DependencyProperty
- public Brush IconStroke
- {
- get { return (Brush)GetValue(IconStrokeProperty); }
- set { SetValue(IconStrokeProperty, value); }
- }
- public static readonly DependencyProperty IconStrokeProperty =
- DependencyProperty.Register("IconStroke", typeof(Brush), typeof(TreeGrid),
- new PropertyMetadata(new SolidColorBrush(Colors.LightGray), new PropertyChangedCallback(TreeGrid.OnIconStrokePropertyChanged)));
-
- private static void OnIconStrokePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
- {
- if (obj is TreeGrid)
- {
- (obj as TreeGrid).OnIconStrokeValueChanged();
- }
- }
-
- protected void OnIconStrokeValueChanged()
- {
-
- }
- #endregion
-
- #region CellBorderBrush DependencyProperty
- public Brush CellBorderBrush
- {
- get { return (Brush)GetValue(CellBorderBrushProperty); }
- set { SetValue(CellBorderBrushProperty, value); }
- }
- public static readonly DependencyProperty CellBorderBrushProperty =
- DependencyProperty.Register("CellBorderBrush", typeof(Brush), typeof(TreeGrid),
- new PropertyMetadata(new SolidColorBrush(Colors.LightGray), new PropertyChangedCallback(TreeGrid.OnCellBorderBrushPropertyChanged)));
-
- private static void OnCellBorderBrushPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
- {
- if (obj is TreeGrid)
- {
- (obj as TreeGrid).OnCellBorderBrushValueChanged();
- }
- }
-
- protected void OnCellBorderBrushValueChanged()
- {
-
- }
- #endregion
-
- protected override DependencyObject GetContainerForItemOverride()
- {
- return new TreeGridItem();
- }
-
- protected override bool IsItemItsOwnContainerOverride(object item)
- {
- return item is TreeGridItem;
- }
-
- protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
- {
- base.OnItemsChanged(e);
- }
- }
-
- public class TreeGridItem : TreeViewItem
- {
- public event EventHandler IconStateChanged;
- static TreeGridItem()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeGridItem), new FrameworkPropertyMetadata(typeof(TreeGridItem)));
- }
-
- public TreeGridItem()
- {
- this.DataContextChanged += TreeGridItem_DataContextChanged;
- }
-
- private void TreeGridItem_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
- {
- if (DataContext != null && DataContext is TreeItemData treeData)
- {
- this.SetBinding(IsExpandedProperty, new Binding("IsExpanded") { Source = treeData, Mode = BindingMode.TwoWay });
- }
- }
-
- protected override void OnVisualParentChanged(DependencyObject oldParent)
- {
- base.OnVisualParentChanged(oldParent);
- }
-
- protected override DependencyObject GetContainerForItemOverride()
- {
- return new TreeGridItem();
- }
-
- protected override bool IsItemItsOwnContainerOverride(object item)
- {
- return item is TreeGridItem;
- }
- }
-
- /*
- * https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/GridViewRowPresenter.cs,ace7d38fc902993d
- * GridViewRow里的每个元素,增加了一个默认的Margin,这样在设置边框的时候会比较麻烦,在运行时去掉
- */
- public class TreeGridCell : ContentControl
- {
- static TreeGridCell()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeGridCell), new FrameworkPropertyMetadata(typeof(TreeGridCell)));
- }
-
- public TreeGridCell()
- {
- Loaded += TreeGridCell_Loaded;
- }
-
- private void TreeGridCell_Loaded(object sender, RoutedEventArgs e)
- {
- Loaded -= TreeGridCell_Loaded;
- var p = VisualTreeHelper.GetParent(this);
- if (p != null && p is FrameworkElement f && f.Margin.Left > 0)
- {
- f.Margin = new Thickness(0);
- }
- }
- }
-
- public static class TreeHelper
- {
- public static T FindParent<T>(this DependencyObject obj)
- {
- var p = VisualTreeHelper.GetParent(obj);
- if (p == null)
- {
- return default(T);
- }
- if (p is T tt)
- {
- return tt;
- }
- return FindParent<T>(p);
- }
-
- public static T FindTreeResource<T>(this FrameworkElement obj, string key)
- {
- if (obj == null)
- {
- return default(T);
- }
- var r = obj.TryFindResource(key);
- if (r == null)
- {
- r = Application.Current.TryFindResource(key);
- }
- if (r != null && r is T t)
- {
- return t;
- }
-
- var p = FindParent<FrameworkElement>(obj);
- if (p != null)
- {
- return FindTreeResource<T>(p, key);
- }
- return default(T);
- }
- }
- }
3.TreeGrid.xaml
- <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="clr-namespace:TreeView.TreeDataGrid.Controls"
- >
- <SolidColorBrush x:Key="TreeIconStroke" Color="GreenYellow" />
-
- <Style x:Key="TreeGridItemStyle" TargetType="{x:Type local:TreeGridItem}">
- <Setter Property="Foreground" Value="Black"/>
- <Setter Property="Background" Value="Transparent"/>
- <Setter Property="IsExpanded" Value="True"/>
- <Setter Property="BorderBrush" Value="Wheat"/>
- <Setter Property="BorderThickness" Value="0,0,0,1"/>
-
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type local:TreeGridItem}">
- <StackPanel>
- <Border Name="Bd"
- Background="Transparent"
- BorderBrush="{TemplateBinding BorderBrush}"
- Padding="{TemplateBinding Padding}">
- <GridViewRowPresenter x:Name="PART_Header"
- Content="{TemplateBinding Header}"
- Columns="{Binding Path=Columns,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:TreeGrid}}" />
- </Border>
- <ItemsPresenter x:Name="ItemsHost" />
- </StackPanel>
-
- <ControlTemplate.Triggers>
-
- <Trigger Property="IsExpanded" Value="false">
- <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/>
- </Trigger>
-
- <MultiTrigger>
- <MultiTrigger.Conditions>
- <Condition Property="HasHeader" Value="false"/>
- <Condition Property="Width" Value="Auto"/>
- </MultiTrigger.Conditions>
- <Setter TargetName="PART_Header" Property="MinWidth" Value="75"/>
- </MultiTrigger>
- <MultiTrigger>
- <MultiTrigger.Conditions>
- <Condition Property="HasHeader" Value="false"/>
- <Condition Property="Height" Value="Auto"/>
- </MultiTrigger.Conditions>
- <Setter TargetName="PART_Header" Property="MinHeight" Value="19"/>
- </MultiTrigger>
- <MultiTrigger>
- <!--移动变色-->
- <MultiTrigger.Conditions>
- <Condition Property="IsFocused" Value="False"/>
- <Condition SourceName="Bd" Property="IsMouseOver" Value="true"/>
- </MultiTrigger.Conditions>
- <Setter Property="Background" Value=" red" TargetName="Bd"/>
- </MultiTrigger>
- <Trigger Property="IsSelected" Value="true">
- <!--选中的背景颜色-->
- <Setter TargetName="Bd" Property="Background" Value="YellowGreen"/>
-
- <!--<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>-->
- <Setter Property="Foreground" Value="Red"/>
- </Trigger>
- <!--隔行换色-->
- <!--<Trigger Property="AlternationIndex" Value="0" >
- <Setter TargetName="Bd" Property="Background" Value="blue" />
- </Trigger>
- <Trigger Property="AlternationIndex" Value="2" >
- <Setter TargetName="Bd" Property="Background" Value="black" />
- </Trigger>-->
- <!--<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=local:TreeGrid}, Path=Columns.Count }" Value="0">
- <Setter TargetName="Bd" Property="Background" Value="#FFD3D3D3"/>
- </DataTrigger>
- <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=local:TreeGrid}, Path=Columns.Count}" Value="2">
- <Setter TargetName="Bd" Property="Background" Value="#FFE6E6E6"/>
- </DataTrigger>-->
- <MultiTrigger>
- <MultiTrigger.Conditions>
- <Condition Property="IsSelected" Value="true"/>
- <Condition Property="IsSelectionActive" Value="false"/>
- </MultiTrigger.Conditions>
- <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
- <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
- </MultiTrigger>
- <Trigger Property="IsEnabled" Value="false">
- <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
- </Trigger>
- </ControlTemplate.Triggers>
-
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- <Style.Triggers>
- <!--隔行换色-->
- <Trigger Property="AlternationIndex" Value="0" >
- <Setter Property="Background" Value="#e7e7e7" />
- </Trigger>
- <Trigger Property="AlternationIndex" Value="1" >
- <Setter Property="Background" Value="#f2f2f2" />
- </Trigger>
- </Style.Triggers>
- </Style>
-
- <Style TargetType="{x:Type local:TreeGridItem}" BasedOn="{StaticResource TreeGridItemStyle}"/>
-
- <Style TargetType="{x:Type local:TreeGridCell}">
- <Setter Property="HorizontalContentAlignment" Value="Center"/>
- <Setter Property="VerticalContentAlignment" Value="Center"/>
- <Setter Property="BorderBrush" Value="Red"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type local:TreeGridCell}">
- <Border x:Name="CellBorder"
- Margin="0,0,-0.5,0"
- Background="{TemplateBinding Background}"
- BorderBrush="Red"
- BorderThickness="0,0,0,1">
- <ContentControl Content="{TemplateBinding Content}"
- ContentTemplate="{TemplateBinding ContentTemplate}"
- HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
- VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
- SnapsToDevicePixels="True"/>
- </Border>
- <!--BorderBrush="Red"下划线颜色-->
- <!--<ControlTemplate.Triggers>
- <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:TreeGrid},Path=ShowCellBorder}" Value="true">
- <Setter TargetName="CellBorder" Property="BorderBrush" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:TreeGrid},Path=CellBorderBrush}" />
- </DataTrigger>
- </ControlTemplate.Triggers>-->
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
-
- <Style TargetType="{x:Type local:TreeGrid}">
- <Setter Property="IconStroke" Value="{StaticResource TreeIconStroke}"/>
- <Setter Property="ItemContainerStyle" Value="{StaticResource {x:Type local:TreeGridItem}}"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type local:TreeGrid}">
- <Border Background="{TemplateBinding Background}"
- BorderBrush="{TemplateBinding BorderBrush}"
- BorderThickness="0">
- <!--最大边框-->
- <DockPanel>
- <!--标题栏-->
- <GridViewHeaderRowPresenter IsHitTestVisible="False" Columns="{TemplateBinding Columns}" Height="{TemplateBinding RowHeight}" DockPanel.Dock="Top" >
- </GridViewHeaderRowPresenter>
- <ItemsPresenter />
- </DockPanel>
- </Border>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
- </ResourceDictionary>
4.代码很多,最终的源码格式
源码地址:
https://download.csdn.net/download/u012563853/89003286
本文来源:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。