WPF开发中自定义DataGrid样式


实际开发中难免需要自己重写GataGrid样式,以下是我写的一个新样式:

1.view界面样式如下:

<Window x:Class="WPFDemoMVVM.View.DataGridView"
		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:WPFDemoMVVM.View"
		xmlns:hr="clr-namespace:WPFDemoMVVM.Helpers"
		xmlns:be="clr-namespace:WPFDemoMVVM.Behaviors"
		xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
		mc:Ignorable="d"
		Title="DataGridView" Height="600" Width="800">
	<Window.Resources>
		<CollectionViewSource x:Key="view" Filter="CollectionViewSource_Filter"/>


		<!--datagrid样式-->
		<Style x:Key="DataGridStyleCommon" TargetType="DataGrid">
			<Setter Property="RowHeight" Value="40"/>
			<Setter Property="Background"  Value="#191D2A" />
			<Setter Property="BorderBrush"  Value="{x:Null}" />
			<Setter Property="Foreground" Value="White"/>
			<Setter Property="Opacity" Value="1"/>
			<!--该属性指示是否允许用户调整列宽度-->
			<Setter Property="CanUserResizeColumns"   Value="false" />
			<!--网格线颜色-->
			<Setter Property="VerticalGridLinesBrush" Value="{x:Null}"/>
			<Setter Property="IsReadOnly" Value="True"></Setter>
			<Setter Property="HorizontalGridLinesBrush">
				<Setter.Value>
					<SolidColorBrush Color="#10FFFFFF" />
					<!--网格透明度-->
				</Setter.Value>
			</Setter>
			<!--<Setter Property="VerticalGridLinesBrush">
		 <Setter.Value>
			 <SolidColorBrush Color="#FFEA8777" />
		 </Setter.Value>
	 </Setter>-->
			<!--表格字段显示手动完成-->
			<Setter Property="AutoGenerateColumns" Value="False"></Setter>
			<!--隔行换色 -->
			<Setter Property="AlternationCount" Value="3"></Setter>
			<!--DataGrid控件模板-->
			<Setter Property="Template">
				<Setter.Value>
					<ControlTemplate TargetType="{x:Type DataGrid}">
						<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" x:Name="border"
						 Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
							<ScrollViewer x:Name="DG_ScrollViewer" Focusable="false">
								<ScrollViewer.Template>
									<ControlTemplate TargetType="{x:Type ScrollViewer}">
										<Grid>
											<Grid.ColumnDefinitions>
												<ColumnDefinition x:Name="col_rowheader" Width="1" />
												<ColumnDefinition Width="*" />
												<ColumnDefinition Width="Auto" />
											</Grid.ColumnDefinitions>
											<Grid.RowDefinitions>
												<RowDefinition Height="Auto" />
												<RowDefinition Height="*" />
												<RowDefinition Height="Auto" />
											</Grid.RowDefinitions>
											<!--选中所有行-->
											<Button Command="ApplicationCommands.SelectAll" Focusable="False" Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}}" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}}">
												<Button.Visibility>
													<Binding Path="HeadersVisibility" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}">
														<Binding.ConverterParameter>
															<DataGridHeadersVisibility>All</DataGridHeadersVisibility>
														</Binding.ConverterParameter>
													</Binding>
												</Button.Visibility>
											</Button>
											<!--表格头部-->
											<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.Column="1" Grid.ColumnSpan="2"
												 Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" >
											</DataGridColumnHeadersPresenter>
											<!--主数据区-->
											<Grid Grid.Row="1" Grid.ColumnSpan="2">
												<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" />
											</Grid>
											<!--垂直滑动条-->

											<ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="2" Maximum="{TemplateBinding ScrollableHeight}"
												Orientation="Vertical" Grid.Row="0" Grid.RowSpan="3" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
												Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
												ViewportSize="{TemplateBinding ViewportHeight}" />

											<!--横向滑动条-->
											<!--
									 <ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2"
													Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal"
													Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
													Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
													ViewportSize="{TemplateBinding ViewportWidth}" />-->
										</Grid>
									</ControlTemplate>
								</ScrollViewer.Template>
								<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
							</ScrollViewer>
						</Border>
						<ControlTemplate.Triggers>
							<Trigger Property="IsEnabled" Value="false">
								<Setter Property="Opacity" Value="1" TargetName="border" />
							</Trigger>
						</ControlTemplate.Triggers>
					</ControlTemplate>
				</Setter.Value>
			</Setter>
			<Style.Triggers>
				<Trigger Property="IsGrouping" Value="true">
					<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
				</Trigger>
			</Style.Triggers>

		</Style>

		<!--行头部样式-->
		<Style x:Key="DataGridRowHeaderStyleCommon" TargetType="DataGridRowHeader">
			<Setter Property="HorizontalContentAlignment" Value="Stretch" />
			<Setter Property="VerticalContentAlignment" Value="Center" />
			<Setter Property="Background" Value="Transparent" />
			<Setter Property="BorderBrush" Value="{x:Null}" />
			<Setter Property="BorderThickness" Value="1" />
			<Setter Property="Margin" Value="0,0,0,0" />
			<Setter Property="Template">
				<Setter.Value>
					<ControlTemplate TargetType="{x:Type DataGridRowHeader}">
						<Grid>
							<Border BorderBrush="{TemplateBinding BorderBrush}"
							Background="{TemplateBinding Background}"
							BorderThickness="{TemplateBinding BorderThickness}"
							Padding="{TemplateBinding Padding}"
							Margin="{TemplateBinding Margin}"
							SnapsToDevicePixels="True">
								<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
										  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
										  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
							</Border>
						</Grid>
					</ControlTemplate>
				</Setter.Value>
			</Setter>
		</Style>

		<!--标题栏 列头部样式-->
		<Style x:Key="DataGridColumnHeaderStyleCommon" TargetType="DataGridColumnHeader">
			<Setter Property="SnapsToDevicePixels" Value="True" />
			<Setter Property="MinWidth" Value="15" />
			<Setter Property="MinHeight" Value="28" />
			<!--<Setter Property="Foreground" Value="#FF0FA459" />-->
			<Setter Property="Foreground" Value="{DynamicResource textBoxWhiteColor}" />
			<Setter Property="FontSize"   Value="14" />
			<!--<Setter Property="Cursor"     Value="Hand" />-->
			<Setter Property="Height" Value="30" />
			<Setter Property="Template">
				<Setter.Value>
					<ControlTemplate TargetType="DataGridColumnHeader">
						<!--设置表头的背景等样式-->
						<Border x:Name="BackgroundBorder"  Background="{DynamicResource backgroundGrayColor}"   BorderThickness="0"   BorderBrush="{DynamicResource borderBrushCommonColor}"  Width="Auto">
							<Grid>
								<Grid.ColumnDefinitions>
									<ColumnDefinition Width="*" />
								</Grid.ColumnDefinitions>
								<!--内容-->
								<ContentPresenter  Margin="0,0,0,0"  VerticalAlignment="Center"  HorizontalAlignment="Center" />
								<!--排序图标-->
								<Path x:Name="SortArrow"  Visibility="Collapsed"   Data="M0,0 L1,0 0.5,1 z"  Stretch="Fill"    Grid.Column="2"    
								   Width="8"  Height="6"  Fill="{DynamicResource textBoxWhiteColor}" Margin="0,0,50,0"  VerticalAlignment="Center"  RenderTransformOrigin="1,1" />
								<!--分割线-->
								<Rectangle Visibility="Collapsed"  Width="1" Fill="#d6c79b" HorizontalAlignment="Right"  Grid.ColumnSpan="1"   />
							</Grid>
						</Border>
					</ControlTemplate>
				</Setter.Value>
			</Setter>
		</Style>


		<!--行样式触发-->
		<!--背景色改变必须先设置cellStyle 因为cellStyle会覆盖rowStyle样式-->
		<Style x:Key="DataGridRowStyleCommon"  TargetType="DataGridRow">
			<Setter Property="Background"  Value="#0D0D19"/>
			<Setter Property="Height"  Value="40" />
			<Setter Property="Foreground" Value="White" />
			<Style.Triggers>
				<!--隔行换色-->
				<!--<Trigger Property="AlternationIndex"  Value="0">
			<Setter Property="Background"   Value="{x:Null}" />
		</Trigger>-->
				<!--<Trigger Property="AlternationIndex"   Value="1">
			<Setter Property="Background" Value="#FFD4C9F9" />
		</Trigger>
		<Trigger Property="AlternationIndex"   Value="2">
			<Setter Property="Background" Value="#FFFFCFC7" />
		</Trigger>-->
				<Trigger Property="IsMouseOver"   Value="True">
					<Setter Property="Foreground" Value="White"/>
					<Setter Property="Background"  Value="#191D2A" />
					<Setter Property="Cursor" Value="Hand"/>
					<Setter Property="Opacity" Value="0.6"></Setter>
				</Trigger>
				<Trigger Property="IsSelected" Value="True">
					<!--<Setter Property="Foreground"   Value="#FFF31006" />-->
					<Setter Property="Opacity" Value="1"></Setter>
					<Setter Property="Background" Value="#1D1D2A"/>
				</Trigger>
			</Style.Triggers>
		</Style>

		<!--单元格样式触发-->
		<Style x:Key="DataGridCellStyleCommon" TargetType="DataGridCell">
			<Setter Property="Template">
				<Setter.Value>
					<ControlTemplate TargetType="DataGridCell">
						<TextBlock TextAlignment="Center"  VerticalAlignment="Center">    
					<ContentPresenter />
						</TextBlock>
					</ControlTemplate>
				</Setter.Value>
			</Setter>
			<Style.Triggers>
				<Trigger Property="IsSelected" Value="True">
					<Setter Property="Foreground" Value="White" />
					<Setter Property="FontWeight" Value="Bold"/>
				</Trigger>
				<Trigger Property="IsMouseOver" Value="True">
					<Setter Property="Foreground" Value="White"/>
				</Trigger>
			</Style.Triggers>
		</Style>

	</Window.Resources>
	<Grid>
		<Grid.RowDefinitions>
			<RowDefinition/>
			<RowDefinition Height="80"/>
		</Grid.RowDefinitions>
		<StackPanel Grid.Row="0" Height="600" Orientation="Vertical">
			<Grid Width="auto">
				<DataGrid Name="userInfoGrid"  AutoGenerateColumns="False" Height="360" HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalAlignment="Top" IsReadOnly="True" CanUserAddRows="False" VerticalScrollBarVisibility="Auto" EnableRowVirtualization="False"                                  
				Style="{DynamicResource ResourceKey=DataGridStyleCommon}"
				   RowHeaderStyle="{DynamicResource ResourceKey=DataGridRowHeaderStyleCommon}"                    
				   ColumnHeaderStyle="{DynamicResource ResourceKey=DataGridColumnHeaderStyleCommon}"                    
				   RowStyle="{DynamicResource ResourceKey=DataGridRowStyleCommon}"                    
				   CellStyle="{DynamicResource ResourceKey=DataGridCellStyleCommon}" Margin="2 0 5 0" BorderThickness="1" ItemsSource="{Binding CollectionView,Mode=OneWay}"
						  hr:MultiSelectorHelper.MonitorSelectionChanged="True"
hr:MultiSelectorHelper.BindableSelectedItems="{Binding SelectedItems,Mode=OneWayToSource}"
						  >

					<i:Interaction.Behaviors>
						<be:SelectedItemsBehavior BindableSelectedItems="{Binding SelectedItems,Mode=OneWayToSource}"/>
					</i:Interaction.Behaviors>
					<DataGrid.Columns>
						<DataGridTextColumn Binding="{Binding Id}" CanUserSort="False" IsReadOnly="True" Width="50">
							<DataGridTextColumn.HeaderTemplate>
								<DataTemplate>
									<TextBlock Text="编号"/>
								</DataTemplate>
							</DataGridTextColumn.HeaderTemplate>
						</DataGridTextColumn>
						<DataGridTextColumn Binding="{Binding Name}" CanUserSort="False" IsReadOnly="True" Width="*">
							<DataGridTextColumn.HeaderTemplate>
								<DataTemplate>
									<TextBlock Text="账号名称"/>
								</DataTemplate>
							</DataGridTextColumn.HeaderTemplate>
						</DataGridTextColumn>
						<DataGridTextColumn Binding="{Binding Salary}" CanUserSort="False" IsReadOnly="True" Width="*">
							<DataGridTextColumn.HeaderTemplate>
								<DataTemplate>
									<TextBlock Text="金额"/>
								</DataTemplate>
							</DataGridTextColumn.HeaderTemplate>
						</DataGridTextColumn>
					</DataGrid.Columns>
				</DataGrid>



			</Grid>
		</StackPanel>
		<StackPanel Grid.Row="1" Orientation="Horizontal">
			<!--<TextBox x:Name="queryKeyword"  Width="200" Height="50" TextChanged="queryKeyword_TextChanged"/>-->
			<TextBox x:Name="queryKeyword" Text="{Binding QueryKeyword,UpdateSourceTrigger=PropertyChanged}" Width="200" Height="50" />
			<Button Margin="5" Content="Add" Command="{Binding AddCommand}"/>
			<Button Margin="5" Content="Calculate" Command="{Binding CalculateSumSalaryCommand}" CommandParameter="{Binding ElementName=userInfoGrid,Path=SelectedItems}"/>

		</StackPanel>

	</Grid>
</Window>

2.后台ViewModel类DataGridViewModel如下:

public partial class DataGridViewModel :ObservableObject
{

	public List<EmployeeModel> employees;

	[ObservableProperty]
	ICollectionView collectionView;

	[ObservableProperty]
	string queryKeyword;

	[ObservableProperty]
	IList selectedItems;


	partial void OnQueryKeywordChanged(string value) => CollectionView.Refresh();

	public DataGridViewModel() 
	{
		IEnumerable<EmployeeModel> employees =EmployeeModel.FakeMany(5);
		this.employees = new List<EmployeeModel>(employees);
		CollectionView = CollectionViewSource.GetDefaultView(this.employees);
		CollectionView.Filter = (item) =>
		{
			if (string.IsNullOrEmpty(QueryKeyword)) return true ;
			var em = item as EmployeeModel;
			return em.Name.Contains(QueryKeyword,StringComparison.OrdinalIgnoreCase);
		};
	}

	[RelayCommand]
	public void Add()
	{
		employees.Add(EmployeeModel.FakeOne());
		CollectionView.Refresh();
	}

	//[RelayCommand]
	//public void CalculateSumSalary(IList employ)
	//{
	//    var sum = employ.Cast<EmployeeModel>().Sum(x => ((EmployeeModel)x).Salary);
	//}

	[RelayCommand]
	public void CalculateSumSalary()
	{
		if (SelectedItems != null)
		{
			var sum = SelectedItems.Cast<EmployeeModel>().Sum(x => ((EmployeeModel)x).Salary);
		}

		foreach (var item in employees)
		{
			item.IsSelected = item.Salary > 15000;
		}
		collectionView.Refresh();
	}

}

3.效果图如下:

如果本文介绍对你有帮助,可以一键四连:点赞+评论+收藏+推荐,谢谢!