datagrid是开发中常用的一个数据展示控件,主要用来展示表格数据。
使用`ItemsSource`绑定数据源,后台构造数据源,双向绑定模式下,数据变化时可反应到界面,界面的数据更改也能应用到数据源。
<Window x:Class="Demo.View.DataGridDemoView"
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:Demo.View"
mc:Ignorable="d"
Title="DataGridDemoView" Height="450" Width="800">
<Grid>
<DataGrid AutoGenerateColumns="False"
ItemsSource="{Binding Items}"
Name="dataGrid">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding name}" />
<DataGridTextColumn Header="Math" Binding="{Binding math}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
using Demo.Base;
using Demo.Model;
using System.Collections.ObjectModel;
namespace Demo.ViewModel
{
public class DataGridDemoViewModel : NotifyPropertyObject
{
private ObservableCollection<DataGridModel> _dataGridModels = new ObservableCollection<DataGridModel>();
public ObservableCollection<DataGridModel> Items
{
get { return _dataGridModels; }
set
{
_dataGridModels = value;
this.RaisePropertyChanged("Items");
}
}
public DataGridDemoViewModel()
{
DataGridModel model1 = new DataGridModel();
model1.name = "张三";
model1.math = "100";
Items.Add(model1);
DataGridModel model2 = new DataGridModel();
model2.name = "张三";
model2.math = "88";
Items.Add(model2);
DataGridModel model3 = new DataGridModel();
model3.name = "李四";
model3.math = "87";
Items.Add(model3);
DataGridModel model4 = new DataGridModel();
model4.name = "李四";
model4.math = "98";
Items.Add(model4);
}
}
}
using Demo.Base;
namespace Demo.Model
{
public class DataGridModel : NotifyPropertyObject
{
private string _name;
public string name
{
get { return _name; }
set { _name = value; }
}
public string _math;
public string math
{
get { return _math; }
set { _math = value; }
}
}
}
NotifyPropertyObject
这里继承于INotifyPropertyChanged
用来做属性更改通知,数据源变化即时反应到界面。
使用RowDetailsTemplate为行详细信息指定模板,选中某一行时,可以显示该行的详细信息。
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<TextBlock Text="{Binding detail}"></TextBlock>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
public class DataGridModel : NotifyPropertyObject
{
private string _name;
public string name
{
get { return _name; }
set { _name = value; }
}
public string _math;
public string math
{
get { return _math; }
set { _math = value; }
}
public string detail
{
get
{
return $"{name}的分数为{math}";
}
}
}
通过Style设置颜色值,结合触发器我们可以按照一定的条件改变行的颜色,比如选中行时,获取鼠标移入行内时,代码如下:
<DataGrid ItemsSource="{Binding TableColorModels}">
<DataGrid.RowStyle >
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="LightPink"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#90F670"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="第一项" Binding="{Binding item1}"></DataGridTextColumn>
<DataGridTextColumn Header="第二项" Binding="{Binding item2}"></DataGridTextColumn>
<DataGridTextColumn Header="第三项" Binding="{Binding item3}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
我们可以通过转换器IValueConverter
或者IMultiValueConverter
获取到数据,然后根据你想要的条件进行颜色值的返回。
//TableColorView.xaml
<Window x:Class="Demo.TableColorView"
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:Demo"
xmlns:common="clr-namespace:Demo.Common"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<common:MultiBindingConverter x:Key="MultiBindingConverter" />
</Window.Resources>
<Grid>
<DataGrid ItemsSource="{Binding TableColorModels}">
<DataGrid.RowStyle >
<Style TargetType="DataGridRow">
<Setter Property="Background">
<Setter.Value>
<MultiBinding Converter="{StaticResource MultiBindingConverter}">
<Binding Path="."/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="第一项" Binding="{Binding item1}"></DataGridTextColumn>
<DataGridTextColumn Header="第二项" Binding="{Binding item2}"></DataGridTextColumn>
<DataGridTextColumn Header="第三项" Binding="{Binding item3}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
//MultiBindingConverter.cs
using System;
using System.Windows.Data;
using System.Windows.Media;
namespace Demo.Common
{
/// <summary>
/// 绑定多参数的值转换器
/// </summary>
public class MultiBindingConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values != null)
{
return Brushes.LightBlue;
}
else
{
return "";
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
有时候我们需要使用鼠标拖动行,对数据进行重新排序,要实现此效果,我们可以通过编写MouseMove,Drop这两个事件来实现,大致思路,鼠标左键按下移动的时候,我们获取到当前行信息,然后启用拖放操作,将行放置到目标行上时,我们改变数据源的顺序即可,参考代码如下:
//datagrid控件上启用拖拽,并添加事件
AllowDrop="True"
PreviewMouseMove="dataGrid_PreviewMouseMove"
Drop="dataGrid_Drop"、
//事件实现
private void dataGrid_PreviewMouseMove(object sender, MouseEventArgs e)
{
try
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DataGrid dataGrid = sender as DataGrid;
//if (dataGrid.BeginEdit()) return;
_preRow = FindVisualParent<DataGridRow>(e.OriginalSource as FrameworkElement);
if (_preRow != null)
{
DragDrop.DoDragDrop(_preRow, _preRow.DataContext, DragDropEffects.Move);
dataGrid.SelectedItem = _preRow.DataContext;
}
}
}catch(Exception ex)
{
}
}
private T FindVisualParent<T>(UIElement element) where T : UIElement
{
UIElement parent = element;
while (parent != null)
{
T correctlyTyped = parent as T;
if (correctlyTyped != null)
{
return correctlyTyped;
}
parent = VisualTreeHelper.GetParent(parent) as UIElement;
}
return null;
}
private void dataGrid_Drop(object sender, DragEventArgs e)
{
try
{
DataGridRow dr = FindVisualParent<DataGridRow>(e.OriginalSource as FrameworkElement);
if (dr != null)
{
int index = dr.GetIndex();
int preindex = _preRow.GetIndex();
ObservableCollection<DataGridModel> items = (this.DataContext as DataGridDemoViewModel).Items;
if (index > items.Count - 1) return;
DataGridModel item = null;
for (int i = 0; i < items.Count; i++)
{
if (i == preindex)
{
item = items[i]; break;
}
}
if (item != null)
{
items.RemoveAt(preindex);
items.Insert(index, item);
}
}
}
catch(Exception ex)
{
}
}