1. 源起
今天想用WPF的DataGrid控件,实现如下功能:

如上图,表格有四列:序号、名称、别名、操作。其中名称列固定,不可修改;别名列可以修改。点击【修改】按钮后,按钮标题变为【完成】,对应的别名列单元格显示文本框,文本框内默认显示原有的别名;点击【完成】按钮,文本框消失,单元格内显示为修改后的别名,按钮标题变为【修改】。
2. 实现
新建一个WPF窗体Window2,Window2.xaml如下:
<Window x:Class="WpfApp1.Window2"
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"
mc:Ignorable="d"
Title="Window2" Height="300" Width="400" Loaded="Window2_OnLoaded">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Foreground" Value="#37acf4"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="#37acf4"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ButtonBase">
<Border x:Name="bd" CornerRadius="2" BorderBrush="{x:Null}" BorderThickness="0" Background="{TemplateBinding Background}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<Border BorderThickness="0,0,0,1" BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="#999"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bd" Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<DataGrid x:Name="DataGrid" AutoGenerateColumns="False" ItemsSource="{Binding DataList}"
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserResizeColumns="False"
CanUserSortColumns="False" CanUserReorderColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="序号" Binding="{Binding Id}" Width="60"/>
<DataGridTextColumn Header="名称" Binding="{Binding Name}" Width="*"/>
<DataGridTemplateColumn Header="别名" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock x:Name="Block" Text="{Binding AliasName}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBox x:Name="Box" Text="{Binding AliasName,UpdateSourceTrigger=LostFocus}" Width="100"
VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="Collapsed"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="操作" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Button Content="修改" Tag="{Binding Id}"
VerticalAlignment="Center" HorizontalAlignment="Center"
Click="Edit_OnClick"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Window2.xaml.cs:
using System;
using System.Windows;
using System.Windows.Controls;
using WpfApp1.ViewModels;
namespace WpfApp1
{
/// <summary>
/// Window2.xaml 的交互逻辑
/// </summary>
public partial class Window2 : Window
{
private WindowViewModel _view;
public Window2()
{
InitializeComponent();
_view = new WindowViewModel();
DataContext = _view;
}
private void Window2_OnLoaded(object sender, RoutedEventArgs e)
{
_view.Init();
}
private void Edit_OnClick(object sender, RoutedEventArgs e)
{
if (!(sender is Button btn)) return;
if (btn.Tag == null) return;
var id = 0; // 数据源模型的Id肩负着DataGrid中行号的作用
if (!int.TryParse(btn.Tag.ToString(), out id)) return;
var columns = DataGrid.Columns;
var column = columns[2];
var cell = column.GetCellContent(DataGrid.Items[id - 1]);
var grid = cell.GetVisualChild<Grid>();
var title = btn.Content.ToString();
foreach (FrameworkElement child in grid.Children)
{
if (child.Name == "Block")
{
if (title == "修改")
child.Visibility = Visibility.Collapsed;
else if (title == "完成")
child.Visibility = Visibility.Visible;
}
else if (child.Name == "Box")
{
if (title == "修改")
child.Visibility = Visibility.Visible;
else if (title == "完成")
child.Visibility = Visibility.Collapsed;
}
}
if (title == "修改")
btn.Content = "完成";
else if (title == "完成")
btn.Content = "修改";
}
}
}
WindowViewModel:
using System.Collections.Generic;
using WpfApp1.Common;
using WpfApp1.Models;
namespace WpfApp1.ViewModels
{
public class WindowViewModel : PropertyChangedBase
{
private List<TestViewModel> _dataList = new List<TestViewModel>();
public List<TestViewModel> DataList
{
get => _dataList;
set => SetValue(ref _dataList, value, nameof(DataList));
}
public void Init()
{
DataList.Add(new TestViewModel { Id = 1, Name = "电机电压", AliasName = "电压" });
DataList.Add(new TestViewModel { Id = 2, Name = "电机电流", AliasName = "电流" });
DataList.Add(new TestViewModel { Id = 3, Name = "电机功率", AliasName = "功率" });
DataList.Add(new TestViewModel { Id = 4, Name = "电机温度", AliasName = "温度" });
}
}
}
PropertyChangedBase:
using System.Collections.Generic;
using System.ComponentModel;
namespace WpfApp1.Common
{
/// <summary>
/// 用于通知属性变更的基类
/// </summary>
public class PropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void SetValue<T>(ref T field, T value, string propertyName)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return;
field = value;
OnPropertyChanged(propertyName);
}
}
}
TestViewModel:
using WpfApp1.Common;
namespace WpfApp1.Models
{
public class TestViewModel : PropertyChangedBase
{
private int _id;
public int Id
{
get => _id;
set => SetValue(ref _id, value, nameof(Id));
}
private string _name = "";
public string Name
{
get => _name;
set => SetValue(ref _name, value, nameof(Name));
}
private string _aliasName = "";
public string AliasName
{
get => _aliasName;
set => SetValue(ref _aliasName, value, nameof(AliasName));
}
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set => SetValue(ref _isSelected, value, nameof(IsSelected));
}
}
}
至此,完成了所有需求。
3. 效果

由于上面所贴代码为完成代码,就不再另行上传项目了。
转自:https://www.cnblogs.com/stonemqy/p/11685882.html
