
需求:
如上图所示。最后两列的数据可以修改。在MVVM框架中还是很好实现的。
1.DataGrid 的数据源是用对应的ObservableCollection 的集合绑定。
2.修改要编辑列数据的列模板
<DataGridTemplateColumn Width="120" Header="VernierOverlayX" HeaderStyle="{StaticResource ColumnHeaderStyle}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<hc:NumericUpDown HorizontalContentAlignment="Center" VerticalContentAlignment="Center" IsEnabled="True" ValueFormat="N6" Value="{Binding VernierOverlayXInput, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="120" Header="VernierOverlayY" HeaderStyle="{StaticResource ColumnHeaderStyle}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<hc:NumericUpDown HorizontalContentAlignment="Center" VerticalContentAlignment="Center" IsEnabled="True" ValueFormat="N6" Value="{Binding VernierOverlayYInput, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
关键功能说明
1. NumericUpDown 限制规则
ValueFormat="N6"→ 最多保留 6 位小数Value="{Binding ..., UpdateSourceTrigger=PropertyChanged}"→ 输入实时同步到数据源- 自动限制只能输入数字 / 小数点,无法输入文字
- 支持正负 float 数值
2. 实体类要求(ViewModel 绑定模型)
确保你的 TestResultDetail 模型里这两个字段是 float / double 类型:
private float _vernierOverlayXInput;
/// <summary>
/// (用户从UI端输入)
/// </summary>
[MfFieldIgnore]
public float VernierOverlayXInput
{
get => _vernierOverlayXInput;
set
{
_vernierOverlayXInput = value;
OnPropertyChanged();
}
}
private float _vernierOverlayYInput;
/// <summary>
/// (用户从UI端输入)
/// </summary>
[MfFieldIgnore]
public float VernierOverlayYInput
{
get => _vernierOverlayYInput;
set
{
_vernierOverlayYInput = value;
OnPropertyChanged();
}
}
3. 保存功能实现(ViewModel 代码)
using Microsoft.Toolkit.Mvvm;
using Microsoft.Toolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
public class MainViewModel : ObservableObject
{
// 绑定列表
public ObservableCollection<TestResultDetail> TestResultDetailList { get; set; } = new();
// 保存命令
public IRelayCommand SaveDataCommand { get; }
public MainViewModel()
{
// 初始化保存命令
SaveDataCommand = new RelayCommand(SaveDataToFile);
}
// 保存逻辑(可改成保存到数据库/JSON/CSV)
private void SaveDataToFile()
{
StringBuilder sb = new();
// 写入表头
sb.AppendLine("ShotPosition,PointPosition,TestNumber,X0,Y0,X180,Y180,TisX,TisY,CorrectionX,CorrectionY,VernierOverlayX,VernierOverlayY");
// 写入每一行数据
foreach (var item in TestResultDetailList)
{
sb.AppendLine($"{item.ShotData},{item.PointPosData},{item.TestNumber},{item.X0},{item.Y0},{item.X180},{item.Y180},{item.TisX},{item.TisY},{item.CorrectionX},{item.CorrectionY},{item.VernierOverlayX},{item.VernierOverlayY}");
}
// 保存到 CSV 文件
File.WriteAllText("TestResultData.csv", sb.ToString(), Encoding.UTF8);
// 提示保存成功(可替换为 MessageBox)
Console.WriteLine("数据保存成功!");
}
}