• [WPF] 操作DataGrid单元格


    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. 效果

    由于上面所贴代码为完成代码,就不再另行上传项目了。

  • 相关阅读:
    [转]Native进程的运行过程
    android ARM 汇编学习 —— hello world
    android ARM 汇编学习—— 在 android 设备上编译c/cpp代码并用objdump/readelf等工具分析
    Linux buffer/cache异同
    分布式消息队列RocketMQ与Kafka架构上的巨大差异之1 -- 为什么RocketMQ要去除ZK依赖?
    kafka对比RocketMQ(转)
    Jmeter测试webocket协议
    Linux atop监控工具部署
    MySql计算两个日期的时间差函数
    Python selenium —— 一定要会用selenium的等待,三种等待方式解读(转)
  • 原文地址:https://www.cnblogs.com/stonemqy/p/11685882.html
Copyright © 2020-2023  润新知