<Window x:Class="CrazyCoder.Views.ModbusTcpWindow"
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="Modbus TCP 工具" Height="750" Width="1100" WindowStartupLocation="CenterScreen">
<Window.Resources>
<Style x:Key="GroupBorder" TargetType="Border">
<Setter Property="BorderBrush" Value="#D0D0D0"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Margin" Value="0,0,0,6"/>
</Style>
<Style x:Key="SectionTitle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="4,3"/>
<Setter Property="FontSize" Value="13"/>
</Style>
<Style x:Key="ConfigLabel" TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="4,2"/>
</Style>
<Style x:Key="ConfigComboBox" TargetType="ComboBox">
<Setter Property="Margin" Value="2"/>
<Setter Property="Height" Value="26"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
<Style x:Key="ConfigTextBox" TargetType="TextBox">
<Setter Property="Margin" Value="2"/>
<Setter Property="Height" Value="26"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="#D0D0D0"/>
</Style>
<Style x:Key="ActionButton" TargetType="Button">
<Setter Property="Height" Value="30"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Padding" Value="8,0"/>
</Style>
<Style x:Key="BigButton" TargetType="Button">
<Setter Property="Height" Value="40"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</Window.Resources>
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="320"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- ============ 左侧:配置面板 ============ -->
<ScrollViewer Grid.Column="0" VerticalScrollBarVisibility="Auto" Margin="0,0,4,0">
<StackPanel>
<!-- 连接配置 -->
<Border Style="{StaticResource GroupBorder}">
<StackPanel>
<TextBlock Text="连接配置" Style="{StaticResource SectionTitle}"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="模式" Style="{StaticResource ConfigLabel}"/>
<ComboBox Grid.Row="0" Grid.Column="1"
ItemsSource="{Binding ModeOptions}"
SelectedIndex="{Binding SelectedMode, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigComboBox}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="地址" Style="{StaticResource ConfigLabel}"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ServerAddress, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigTextBox}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="端口" Style="{StaticResource ConfigLabel}"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Port, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigTextBox}"/>
<Button Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
Content="{Binding ConnectButtonText}"
Command="{Binding ToggleConnectCommand}"
Style="{StaticResource BigButton}" Foreground="White"/>
</Grid>
</StackPanel>
</Border>
<!-- Modbus 操作(主站模式) -->
<Border Style="{StaticResource GroupBorder}">
<StackPanel>
<TextBlock Text="Modbus 操作" Style="{StaticResource SectionTitle}"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="站号" Style="{StaticResource ConfigLabel}"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding SlaveAddress, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigTextBox}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="功能" Style="{StaticResource ConfigLabel}"/>
<ComboBox Grid.Row="1" Grid.Column="1"
ItemsSource="{Binding FuncCodeOptions}"
SelectedIndex="{Binding FunctionCodeIndex, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigComboBox}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="地址" Style="{StaticResource ConfigLabel}"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding StartAddress, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigTextBox}"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="数量" Style="{StaticResource ConfigLabel}"/>
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding ReadCount, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigTextBox}"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="值" Style="{StaticResource ConfigLabel}"/>
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding WriteValue, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigTextBox}"/>
</Grid>
<Button Content="执行" Command="{Binding ExecuteCommand}"
Style="{StaticResource BigButton}" Foreground="White" Background="#218868"/>
<TextBox Text="{Binding ReadResult, Mode=OneWay}" IsReadOnly="True"
Style="{StaticResource ConfigTextBox}" Height="60"
AcceptsReturn="True" TextWrapping="Wrap" Margin="2,4,2,2"/>
</StackPanel>
</Border>
<!-- 从站配置 -->
<Border Style="{StaticResource GroupBorder}">
<StackPanel>
<TextBlock Text="从站配置" Style="{StaticResource SectionTitle}"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="地址" Style="{StaticResource ConfigLabel}"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding SlaveDataAddress, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigTextBox}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="数量" Style="{StaticResource ConfigLabel}"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding SlaveDataCount, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigTextBox}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="模式" Style="{StaticResource ConfigLabel}"/>
<ComboBox Grid.Row="2" Grid.Column="1"
ItemsSource="{Binding DataModeOptions}"
SelectedIndex="{Binding DataModeIndex, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ConfigComboBox}"/>
<Button Grid.Row="2" Grid.Column="2" Content="刷新" Command="{Binding RefreshDataCommand}"
Style="{StaticResource ActionButton}" Width="50"/>
</Grid>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
<!-- ============ 右侧:日志 + 从站数据 ============ -->
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<!-- 日志 -->
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Style="{StaticResource GroupBorder}" Background="#FFF5E6">
<Grid>
<TextBlock Text="日志" Style="{StaticResource SectionTitle}" VerticalAlignment="Center"/>
<Button HorizontalAlignment="Right" Content="清空" Command="{Binding ClearLogCommand}"
Style="{StaticResource ActionButton}" Margin="0,2,4,2"/>
</Grid>
</Border>
<Border Grid.Row="1" Style="{StaticResource GroupBorder}">
<RichTextBox x:Name="txtLog" IsReadOnly="True" VerticalScrollBarVisibility="Auto"
FontFamily="Consolas" FontSize="12" Background="#1E1E1E" Foreground="#D4D4D4"/>
</Border>
</Grid>
<!-- 分隔 -->
<GridSplitter Grid.Row="1" Height="4" HorizontalAlignment="Stretch" Background="#D0D0D0"/>
<!-- 从站数据表格 -->
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Style="{StaticResource GroupBorder}" Background="#E8F5E9">
<TextBlock Text="从站数据(寄存器列表)" Style="{StaticResource SectionTitle}"/>
</Border>
<Border Grid.Row="1" Style="{StaticResource GroupBorder}">
<ListView x:Name="lvRegisters" ItemsSource="{Binding Registers}" HorizontalContentAlignment="Stretch">
<ListView.View>
<GridView>
<GridViewColumn Header="地址" Width="100" DisplayMemberBinding="{Binding Address}"/>
<GridViewColumn Header="数值(十进制)" Width="150" DisplayMemberBinding="{Binding Value}"/>
<GridViewColumn Header="数值(十六进制)" Width="150" DisplayMemberBinding="{Binding Hex}"/>
</GridView>
</ListView.View>
</ListView>
</Border>
</Grid>
</Grid>
</Grid>
</Window>
|