This commit is contained in:
@@ -78,6 +78,7 @@
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Content="压力校准" Command="{Binding OpenPressureCalibCommand}" Padding="15,8" Margin="5"/>
|
||||
<Button Content="保存到历史" Command="{Binding SaveCommand}" Padding="15,8" Margin="5"/>
|
||||
<Button Content="生成报告" Command="{Binding GenerateReportCommand}" Padding="15,8" Margin="5"/>
|
||||
<Button Content="导出Excel" Command="{Binding ExportCommand}" Padding="15,8" Margin="5"/>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:viewModels="clr-namespace:MembranePoreTester.ViewModels"
|
||||
Title="膜孔径测试系统 (GB/T 32361-2015)"
|
||||
Width="1024" Height="768"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
WindowStartupLocation="CenterScreen" KeyDown="Window_KeyDown">
|
||||
<Window.DataContext>
|
||||
<viewModels:MainViewModel />
|
||||
</Window.DataContext>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using MembranePoreTester.ViewModels;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace MembranePoreTester.Views
|
||||
{
|
||||
@@ -41,5 +42,16 @@ namespace MembranePoreTester.Views
|
||||
var historyWin = new HistoryWindow { SelectedStation = currentStation };
|
||||
historyWin.ShowDialog();
|
||||
}
|
||||
|
||||
|
||||
private void Window_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.P)
|
||||
{
|
||||
var win = new ParameterWindow();
|
||||
win.Owner = this;
|
||||
win.ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
120
Views/ParameterWindow.xaml
Normal file
120
Views/ParameterWindow.xaml
Normal file
@@ -0,0 +1,120 @@
|
||||
<Window x:Class="MembranePoreTester.Views.ParameterWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="运维参数设置" Height="600" Width="800"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<ScrollViewer>
|
||||
<StackPanel Margin="10">
|
||||
<GroupBox Header="加压控制">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="150"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0">加压上限(D300):</Label>
|
||||
<TextBox x:Name="txtPressureUpper" Grid.Row="0" Grid.Column="1"/>
|
||||
<Label Grid.Row="1" Grid.Column="0">加压速率(D280):</Label>
|
||||
<TextBox x:Name="txtPressureRate" Grid.Row="1" Grid.Column="1"/>
|
||||
<Label Grid.Row="2" Grid.Column="0">加压系数(D282):</Label>
|
||||
<TextBox x:Name="txtPressureCoeff" Grid.Row="2" Grid.Column="1"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="高压/低压系数">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<!-- 预留空白 -->
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" FontWeight="Bold">工位</Label>
|
||||
<Label Grid.Row="0" Grid.Column="1" FontWeight="Bold">高压系数</Label>
|
||||
<Label Grid.Row="0" Grid.Column="2" FontWeight="Bold">低压系数</Label>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0">工位1</Label>
|
||||
<TextBox x:Name="txtHPCoeff1" Grid.Row="1" Grid.Column="1" Width="80" HorizontalAlignment="Left"/>
|
||||
<TextBox x:Name="txtLPCoeff1" Grid.Row="1" Grid.Column="2" Width="80" HorizontalAlignment="Left"/>
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0">工位2</Label>
|
||||
<TextBox x:Name="txtHPCoeff2" Grid.Row="2" Grid.Column="1" Width="80" HorizontalAlignment="Left"/>
|
||||
<TextBox x:Name="txtLPCoeff2" Grid.Row="2" Grid.Column="2" Width="80" HorizontalAlignment="Left"/>
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="0">工位3</Label>
|
||||
<TextBox x:Name="txtHPCoeff3" Grid.Row="3" Grid.Column="1" Width="80" HorizontalAlignment="Left"/>
|
||||
<TextBox x:Name="txtLPCoeff3" Grid.Row="3" Grid.Column="2" Width="80" HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="流量系数">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" FontWeight="Bold">工位</Label>
|
||||
<Label Grid.Row="0" Grid.Column="1" FontWeight="Bold">大流量系数</Label>
|
||||
<Label Grid.Row="0" Grid.Column="2" FontWeight="Bold">小流量系数</Label>
|
||||
<Label Grid.Row="1" Grid.Column="0">工位1</Label>
|
||||
<TextBox x:Name="txtLargeFlow1" Grid.Row="1" Grid.Column="1"/>
|
||||
<TextBox x:Name="txtSmallFlow1" Grid.Row="1" Grid.Column="2"/>
|
||||
<Label Grid.Row="2" Grid.Column="0">工位2</Label>
|
||||
<TextBox x:Name="txtLargeFlow2" Grid.Row="2" Grid.Column="1"/>
|
||||
<TextBox x:Name="txtSmallFlow2" Grid.Row="2" Grid.Column="2"/>
|
||||
<Label Grid.Row="3" Grid.Column="0">工位3</Label>
|
||||
<TextBox x:Name="txtLargeFlow3" Grid.Row="3" Grid.Column="1"/>
|
||||
<TextBox x:Name="txtSmallFlow3" Grid.Row="3" Grid.Column="2"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="校准参数">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="150"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0">压力零点校准:</Label>
|
||||
<TextBox x:Name="txtPressureZero" Grid.Row="0" Grid.Column="1"/>
|
||||
<Label Grid.Row="1" Grid.Column="0">压力量程校准:</Label>
|
||||
<TextBox x:Name="txtPressureSpan" Grid.Row="1" Grid.Column="1"/>
|
||||
<Label Grid.Row="2" Grid.Column="0">流量零点校准:</Label>
|
||||
<TextBox x:Name="txtFlowZero" Grid.Row="2" Grid.Column="1"/>
|
||||
<Label Grid.Row="3" Grid.Column="0">流量量程校准:</Label>
|
||||
<TextBox x:Name="txtFlowSpan" Grid.Row="3" Grid.Column="1"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,20,0,0">
|
||||
<!--<Button Content="读取参数" Click="ReadParameters_Click" Width="100" Margin="5"/>-->
|
||||
<Button Content="写入参数" Click="WriteParameters_Click" Width="100" Margin="5"/>
|
||||
<Button Content="关闭" Click="Close_Click" Width="100" Margin="5"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Window>
|
||||
186
Views/ParameterWindow.xaml.cs
Normal file
186
Views/ParameterWindow.xaml.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
using MembranePoreTester.Communication;
|
||||
using MembranePoreTester.ViewModels;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace MembranePoreTester.Views
|
||||
{
|
||||
public partial class ParameterWindow : Window
|
||||
{
|
||||
private readonly IPlcService _plcService;
|
||||
private readonly PlcConfiguration _config;
|
||||
private DispatcherTimer _autoRefreshTimer;
|
||||
private bool _isEditing = false; // 用户是否正在编辑任何文本框
|
||||
|
||||
public ParameterWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
_plcService = App.PlcService;
|
||||
_config = App.PlcConfig;
|
||||
|
||||
// 为所有文本框注册焦点事件(在XAML中设置事件,或在此处统一查找)
|
||||
RegisterTextBoxEvents();
|
||||
|
||||
Loaded += async (s, e) =>
|
||||
{
|
||||
// 启动自动刷新定时器(每秒1次)
|
||||
_autoRefreshTimer = new DispatcherTimer
|
||||
{
|
||||
Interval = TimeSpan.FromSeconds(1)
|
||||
};
|
||||
_autoRefreshTimer.Tick += AutoRefreshTimer_Tick;
|
||||
_autoRefreshTimer.Start();
|
||||
|
||||
// 首次加载时读取一次
|
||||
await ReadParametersAsync();
|
||||
};
|
||||
|
||||
Closed += (s, e) => _autoRefreshTimer?.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为所有文本框注册焦点事件,用于检测编辑状态
|
||||
/// </summary>
|
||||
private void RegisterTextBoxEvents()
|
||||
{
|
||||
// 查找当前窗口中所有文本框(可根据实际布局调整)
|
||||
var textBoxes = FindVisualChildren<System.Windows.Controls.TextBox>(this);
|
||||
foreach (var tb in textBoxes)
|
||||
{
|
||||
tb.GotFocus += (s, e) => _isEditing = true;
|
||||
tb.LostFocus += (s, e) => _isEditing = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时器事件:如果用户未在编辑,则刷新参数
|
||||
/// </summary>
|
||||
private async void AutoRefreshTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
if (!_isEditing)
|
||||
{
|
||||
await ReadParametersAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReadParametersAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 加压控制
|
||||
txtPressureUpper.Text = (await ReadFloatAsync(_config.PressureUpperLimit)).ToString("F3");
|
||||
txtPressureRate.Text = (await ReadFloatAsync(_config.PressureRate)).ToString("F3");
|
||||
txtPressureCoeff.Text = (await ReadFloatAsync(_config.PressureCoeff)).ToString("F3");
|
||||
|
||||
// 高压/低压系数
|
||||
txtHPCoeff1.Text = (await ReadFloatAsync(_config.HPCoeff1)).ToString("F3");
|
||||
txtLPCoeff1.Text = (await ReadFloatAsync(_config.LPCoeff1)).ToString("F3");
|
||||
txtHPCoeff2.Text = (await ReadFloatAsync(_config.HPCoeff2)).ToString("F3");
|
||||
txtLPCoeff2.Text = (await ReadFloatAsync(_config.LPCoeff2)).ToString("F3");
|
||||
txtHPCoeff3.Text = (await ReadFloatAsync(_config.HPCoeff3)).ToString("F3");
|
||||
txtLPCoeff3.Text = (await ReadFloatAsync(_config.LPCoeff3)).ToString("F3");
|
||||
|
||||
// 流量系数
|
||||
txtLargeFlow1.Text = (await ReadFloatAsync(_config.LargeFlowCoeff1)).ToString("F3");
|
||||
txtSmallFlow1.Text = (await ReadFloatAsync(_config.SmallFlowCoeff1)).ToString("F3");
|
||||
txtLargeFlow2.Text = (await ReadFloatAsync(_config.LargeFlowCoeff2)).ToString("F3");
|
||||
txtSmallFlow2.Text = (await ReadFloatAsync(_config.SmallFlowCoeff2)).ToString("F3");
|
||||
txtLargeFlow3.Text = (await ReadFloatAsync(_config.LargeFlowCoeff3)).ToString("F3");
|
||||
txtSmallFlow3.Text = (await ReadFloatAsync(_config.SmallFlowCoeff3)).ToString("F3");
|
||||
|
||||
// 校准参数
|
||||
txtPressureZero.Text = (await ReadFloatAsync(_config.PressureCalibZero)).ToString("F3");
|
||||
txtPressureSpan.Text = (await ReadFloatAsync(_config.PressureCalibSpan)).ToString("F3");
|
||||
txtFlowZero.Text = (await ReadFloatAsync(_config.FlowCalibZero)).ToString("F3");
|
||||
txtFlowSpan.Text = (await ReadFloatAsync(_config.FlowCalibSpan)).ToString("F3");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 静默处理,避免频繁弹窗干扰(可记录日志)
|
||||
System.Diagnostics.Debug.WriteLine($"自动读取参数失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async void WriteParameters_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 加压控制
|
||||
await WriteFloatAsync(_config.PressureUpperLimit, ParseFloat(txtPressureUpper.Text));
|
||||
await WriteFloatAsync(_config.PressureRate, ParseFloat(txtPressureRate.Text));
|
||||
await WriteFloatAsync(_config.PressureCoeff, ParseFloat(txtPressureCoeff.Text));
|
||||
|
||||
// 高压/低压系数
|
||||
await WriteFloatAsync(_config.HPCoeff1, ParseFloat(txtHPCoeff1.Text));
|
||||
await WriteFloatAsync(_config.LPCoeff1, ParseFloat(txtLPCoeff1.Text));
|
||||
await WriteFloatAsync(_config.HPCoeff2, ParseFloat(txtHPCoeff2.Text));
|
||||
await WriteFloatAsync(_config.LPCoeff2, ParseFloat(txtLPCoeff2.Text));
|
||||
await WriteFloatAsync(_config.HPCoeff3, ParseFloat(txtHPCoeff3.Text));
|
||||
await WriteFloatAsync(_config.LPCoeff3, ParseFloat(txtLPCoeff3.Text));
|
||||
|
||||
// 流量系数
|
||||
await WriteFloatAsync(_config.LargeFlowCoeff1, ParseFloat(txtLargeFlow1.Text));
|
||||
await WriteFloatAsync(_config.SmallFlowCoeff1, ParseFloat(txtSmallFlow1.Text));
|
||||
await WriteFloatAsync(_config.LargeFlowCoeff2, ParseFloat(txtLargeFlow2.Text));
|
||||
await WriteFloatAsync(_config.SmallFlowCoeff2, ParseFloat(txtSmallFlow2.Text));
|
||||
await WriteFloatAsync(_config.LargeFlowCoeff3, ParseFloat(txtLargeFlow3.Text));
|
||||
await WriteFloatAsync(_config.SmallFlowCoeff3, ParseFloat(txtSmallFlow3.Text));
|
||||
|
||||
// 校准参数
|
||||
await WriteFloatAsync(_config.PressureCalibZero, ParseFloat(txtPressureZero.Text));
|
||||
await WriteFloatAsync(_config.PressureCalibSpan, ParseFloat(txtPressureSpan.Text));
|
||||
await WriteFloatAsync(_config.FlowCalibZero, ParseFloat(txtFlowZero.Text));
|
||||
await WriteFloatAsync(_config.FlowCalibSpan, ParseFloat(txtFlowSpan.Text));
|
||||
|
||||
MessageBox.Show("参数写入成功");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"写入参数失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private float ParseFloat(string text) => float.TryParse(text, out var val) ? val : 0;
|
||||
|
||||
private async Task<float> ReadFloatAsync(ushort address)
|
||||
{
|
||||
var registers = await ((ModbusTcpPlcService)_plcService).ReadHoldingRegistersAsync(address, 2);
|
||||
byte[] bytes = new byte[4];
|
||||
bytes[0] = (byte)(registers[0] >> 8);
|
||||
bytes[1] = (byte)(registers[0] & 0xFF);
|
||||
bytes[2] = (byte)(registers[1] >> 8);
|
||||
bytes[3] = (byte)(registers[1] & 0xFF);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
|
||||
return BitConverter.ToSingle(bytes, 0);
|
||||
}
|
||||
|
||||
private async Task WriteFloatAsync(ushort address, float value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
|
||||
ushort high = (ushort)((bytes[0] << 8) | bytes[1]);
|
||||
ushort low = (ushort)((bytes[2] << 8) | bytes[3]);
|
||||
await ((ModbusTcpPlcService)_plcService).WriteRegisterAsync(address, high);
|
||||
await ((ModbusTcpPlcService)_plcService).WriteRegisterAsync((ushort)(address + 1), low);
|
||||
}
|
||||
|
||||
private void Close_Click(object sender, RoutedEventArgs e) => Close();
|
||||
|
||||
/// <summary>
|
||||
/// 辅助方法:查找视觉树中的所有指定类型子元素
|
||||
/// </summary>
|
||||
private static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
|
||||
{
|
||||
if (depObj == null) yield break;
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(depObj, i);
|
||||
if (child is T t) yield return t;
|
||||
foreach (var childOfChild in FindVisualChildren<T>(child)) yield return childOfChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<UserControl x:Class="MembranePoreTester.Views.PoreDistributionView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
xmlns:conv="clr-namespace:MembranePoreTester.Converters">
|
||||
<UserControl.Resources>
|
||||
<conv:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
|
||||
@@ -69,12 +70,17 @@
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,0,0,5">
|
||||
<Button Content="添加行" Command="{Binding AddDataPointCommand}" Padding="10,5" Margin="5"/>
|
||||
<Button Content="删除行" Command="{Binding RemoveDataPointCommand}" Padding="10,5" Margin="5"/>
|
||||
|
||||
|
||||
<!-- 新增:模式选择 -->
|
||||
<ComboBox SelectedItem="{Binding TestMode}" Width="80" Margin="5">
|
||||
<ComboBoxItem Content="湿膜" IsSelected="True"/>
|
||||
<ComboBoxItem Content="干膜"/>
|
||||
</ComboBox>
|
||||
<ComboBox SelectedIndex="{Binding SelectedFlowModeIndex}" Width="100" Margin="5">
|
||||
<ComboBoxItem IsSelected="True" Content="大流量"/>
|
||||
<ComboBoxItem Content="小流量"/>
|
||||
</ComboBox>
|
||||
<Button Content="读取PLC" Command="{Binding ReadPlcCommand}" Padding="10,5" Margin="5"/>
|
||||
</StackPanel>
|
||||
<DataGrid ItemsSource="{Binding Record.DataPoints}" AutoGenerateColumns="False" CanUserAddRows="False">
|
||||
@@ -91,7 +97,7 @@
|
||||
|
||||
<!-- 右侧简易数据展示(可用图表库,此处仅用ListBox预览) -->
|
||||
<GroupBox Grid.Column="2" Header="数据预览" Margin="5,0,0,0">
|
||||
<ListBox ItemsSource="{Binding Record.DataPoints}">
|
||||
<!--<ListBox ItemsSource="{Binding Record.DataPoints}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -103,7 +109,10 @@
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</ListBox>-->
|
||||
<GroupBox Grid.Column="2" Header="流量-压力曲线" Margin="5,0,0,0">
|
||||
<oxy:PlotView Model="{Binding PlotModel}" Height="300" Margin="5"/>
|
||||
</GroupBox>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
||||
@@ -122,6 +131,7 @@
|
||||
<TextBlock Text="{Binding RangePercentage, StringFormat={}{0:F1}%}" FontSize="16" VerticalAlignment="Center" Margin="10,0"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<Button Content="流量校准" Command="{Binding OpenFlowCalibCommand}" Padding="15,8" Margin="5"/>
|
||||
<Button Content="生成报告" Command="{Binding GenerateReportCommand}" Padding="15,8" Margin="5"/>
|
||||
<Button Content="保存到历史" Command="{Binding SaveCommand}" Padding="15,8" Margin="5"/>
|
||||
<Button Content="导出Excel" Command="{Binding ExportCommand}" Padding="15,8" Margin="5"/>
|
||||
|
||||
Reference in New Issue
Block a user