HandyControl 是一个强大的WPF开源控件库。它几乎重新定义了原生控件的样式,并提供超过80个功能丰富的自定义控件,能让你的WPF应用在几分钟内拥有现代化的专业外观。

以下是如何为你的淬火炉监控系统应用这一强大工具库的完整指南。

🚀 1. 快速集成 HandyControl

步骤一:通过NuGet安装

在Visual Studio的包管理器控制台运行以下命令,为你的项目安装HandyControl库:

Install-Package HandyControl
步骤二:在App.xaml中应用全局样式

安装完成后,需要在App.xaml中引用HandyControl的全局资源和主题,这是让所有控件变漂亮的关键一步:

<Application x:Class="QuenchingFurnaceMonitor.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <!-- 引入主题(默认为亮色)-->
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
                <!-- 引入控件样式 -->
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>
步骤三:在XAML中引入命名空间

现在,你可以在任何.xaml文件中,通过以下命名空间使用HandyControl的所有强大控件了:

<UserControl ...
             xmlns:hc="https://handyorg.github.io/handycontrol">
    <!-- 页面内容 -->
</UserControl>

🎨 2. 核心控件与应用场景

HandyControl为WPF原生控件带来了全新的面貌,并提供了许多实用的新控件。

  • 美化原生控件:安装后,标准ButtonTextBox等都会自动获得扁平化的现代风格。

    <!-- 原生Button无需任何修改,样式即被HandyControl美化 -->
    <Button Content="常规按钮" Margin="5"/>
    <!-- 使用HandyControl提供的预定义样式快速设置颜色 -->
    <Button Style="{StaticResource ButtonSuccess}" Content="成功按钮" Margin="5"/>
    
  • hc:ToggleSwitch (开关) & hc:WatermarkTextBox (带水印的文本框):提供更直观的开关选择和在输入框为空时显示提示,提升用户体验。

    <hc:ToggleSwitch IsOn="True" />
    <hc:WatermarkTextBox hc:TitleElement.Title="用户名" Watermark="请输入用户名" Width="200" />
    
  • hc:ProgressButton (带进度按钮):非常适合你的淬火炉场景。它可以将“启动”和“停止”等按钮与进度指示相结合。

    <hc:ProgressButton Content="加热中..." IsWorking="True" Value="65" />
    
  • hc:DataGrid 与数据展示hc:DataGrid提供了更美观的表格样式,并可通过附加属性hc:DataGridAttach.ShowRowNumber="True"轻松显示行号。

    <hc:DataGrid ItemsSource="{Binding HistoryData}" AutoGenerateColumns="False" 
                 hc:DataGridAttach.ShowRowNumber="True" BorderThickness="0" Margin="10">
        <hc:DataGrid.Columns>
            <!-- 列定义 -->
        </hc:DataGrid.Columns>
    </hc:DataGrid>
    
  • hc:Card (卡片容器) & hc:Badge (徽章)hc:Card为内容提供带阴影和圆角的容器,hc:Badge用于显示通知数量、状态标识等,适合在数据面板或详情页面中使用。

关于图表HandyControl的核心库本身不包含复杂图表,但它与专业的图表库LiveCharts兼容性很好。你可以保持原有的LiveCharts.Wpf来显示淬火温度曲线。

🌓 3. 主题切换:实现一键换肤

HandyControl内置了亮色(SkinDefault)和暗色(SkinDark)两套主题,并支持运行时动态切换。

你可以将主题切换按钮的命令绑定到MainWindowViewModel中的方法:

using HandyControl.Controls;
using HandyControl.Data;

namespace QuenchingFurnaceMonitor.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        // ... 你的其他属性和命令
        
        private void ExecuteSwitchThemeCommand()
        {
            // 判断当前是否为暗色主题
            if (ThemeManager.CurrentTheme == ThemeType.Dark)
            {
                ThemeManager.CurrentTheme = ThemeType.Default;
            }
            else
            {
                ThemeManager.CurrentTheme = ThemeType.Dark;
            }
        }
    }
}

💬 4. 现代化通知与对话框

Growl 消息通知

Growl用于在屏幕角落显示临时的、无阻隔的消息提示,非常适合代替MessageBox来显示操作结果或状态更新。

using HandyControl.Controls;

// 显示普通信息
Growl.Info("数据保存成功!");
// 显示警告信息
Growl.Warning("加热次数剩余不足100次,请准备更换线圈。");
// 显示错误信息(需手动关闭)
Growl.Error("PLC连接失败!");
Dialog 现代化对话框

当需要用户确认重要操作(如“开始记录”、“停止加热”)或输入信息时,HandyControlDialogMessageBox的完美替代品。

首先,你需要为你的对话框创建一个简单的View和ViewModel。最简化的方式如下:

  1. 创建对话框视图:新建一个UserControl,例如ConfirmDialog.xaml
  2. 在ViewModel中调用
// 在ViewModel中
using HandyControl.Controls;

async Task ExecuteSomeActionAsync()
{
    // 弹出确认对话框,标题为“确认”,内容为“确定要执行此操作吗?”
    var result = await Dialog.Show<string>("确定要执行此操作吗?", "确认");
    
    // 根据用户点击的按钮,result 可能为 DialogResult.Confirm 或 DialogResult.Cancel
    if (result == "确定") // 实际的确认按钮回调值
    {
        // 执行操作
        Growl.Success("操作已执行");
    }
}
NotifyIcon 系统托盘集成

HandyControl内置了NotifyIcon控件,让应用能在后台运行并保持存在感,非常适合监控类应用。将以下代码添加到你的MainWindow.xaml中,即可创建一个标准的托盘图标,并支持双击显示主窗口和右键菜单。

<Window x:Class="QuenchingFurnaceMonitor.Views.MainWindow"
        ...
        xmlns:hc="https://handyorg.github.io/handycontrol">
    <Grid>
        ...
    </Grid>
    <!-- 系统托盘图标 -->
    <hc:NotifyIcon x:Name="NotifyIconContext"
                   Text="淬火炉智能监控系统"
                   Icon="/Resources/Icons/furnace.ico"
                   Visibility="Visible"
                   DoubleClickCommand="{Binding ShowWindowCommand}">
        <hc:NotifyIcon.ContextMenu>
            <ContextMenu>
                <MenuItem Header="显示主界面" Command="{Binding ShowWindowCommand}"/>
                <MenuItem Header="退出" Command="{Binding ExitCommand}"/>
            </ContextMenu>
        </hc:NotifyIcon.ContextMenu>
    </hc:NotifyIcon>
</Window>

✅ 5. 数据验证与TitleElement

HandyControl通过TitleElement附件属性,提供了一种优雅的表单验证和错误提示方式。

<Window ...
        xmlns:hc="https://handyorg.github.io/handycontrol">
    <StackPanel Margin="20">
        <!-- 使用TitleElement附加属性为控件添加描述 -->
        <TextBox hc:TitleElement.Title="加热温度"
                 hc:TitleElement.NeedWidth="120"
                 Text="{Binding Temperature, UpdateSourceTrigger=PropertyChanged}" />
        
        <!-- TitleElement同时也提供了验证错误信息的模板 -->
        <TextBox hc:TitleElement.Title="加热时长(秒)"
                 hc:TitleElement.NeedWidth="120"
                 Text="{Binding Duration, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True}" />
    </StackPanel>
</Window>

在对应的ViewModel中,你需要实现IDataErrorInfo接口来提供验证逻辑,错误信息会通过TitleElement优雅地显示在输入框下方或旁边。

💻 6. 淬火炉项目实战

6.1 集成到你的MainWindow.xaml
<Window x:Class="QuenchingFurnaceMonitor.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:hc="https://handyorg.github.io/handycontrol"
        xmlns:views="clr-namespace:QuenchingFurnaceMonitor.Views"
        Title="淬火炉智能监控系统" 
        Height="800" Width="1400"
        WindowStartupLocation="CenterScreen"
        WindowState="Maximized">
    <Window.Resources>
        <!-- 定义视图与视图模型的映射 -->
        <DataTemplate DataType="{x:Type viewmodels:RealTimeViewModel}">
            <views:RealTimeView/>
        </DataTemplate>
        <!-- 其他视图映射 -->
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="60"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <!-- 顶部菜单栏,使用 HandyControl 的样式 -->
        <Border Grid.Row="0" Background="{DynamicResource PrimaryBrush}">
            <DockPanel>
                <TextBlock Text="淬火炉智能监控系统" FontSize="20" FontWeight="Bold" 
                           Foreground="White" VerticalAlignment="Center" Margin="20,0,0,0"
                           DockPanel.Dock="Left"/>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,20,0">
                    <!-- 使用 HandyControl 预定义按钮样式 -->
                    <Button Style="{StaticResource ButtonPrimary}" Content="实时监控" 
                            Command="{Binding NavigateToRealTimeCommand}" Margin="5"/>
                    <Button Style="{StaticResource ButtonPrimary}" Content="历史查询" 
                            Command="{Binding NavigateToHistoryCommand}" Margin="5"/>
                    <Button Style="{StaticResource ButtonPrimary}" Content="线圈维护" 
                            Command="{Binding NavigateToCoilCommand}" Margin="5"/>
                    <Button Style="{StaticResource ButtonDanger}" Content="退出系统" 
                            Command="{Binding ExitCommand}" Margin="5"/>
                </StackPanel>
            </DockPanel>
        </Border>
        <!-- 动态内容区域 -->
        <ContentControl Grid.Row="1" Content="{Binding CurrentView}"/>
        <!-- 底部状态栏 -->
        <StatusBar Grid.Row="2">
            <StatusBarItem>
                <TextBlock Text="{Binding StatusMessage}"/>
            </StatusBarItem>
            <Separator/>
            <StatusBarItem>
                <!-- 带通知图标的托盘控件 -->
                <hc:Badge Text="3">
                    <hc:ToggleSwitch IsChecked="False"/>
                </hc:Badge>
            </StatusBarItem>
        </StatusBar>
    </Grid>
</Window>
6.2 改进线圈维护视图
<UserControl x:Class="QuenchingFurnaceMonitor.Views.CoilMaintenanceView"
             ... 
             xmlns:hc="https://handyorg.github.io/handycontrol">
    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <!-- 添加新线圈区域 -->
        <hc:Card Grid.Row="0" Margin="0,0,0,20" Header="添加新线圈">
            <StackPanel Orientation="Horizontal" Margin="10">
                <TextBlock Text="线圈名称:" VerticalAlignment="Center" Margin="0,0,5,0"/>
                <hc:WatermarkTextBox Watermark="请输入新线圈编号" 
                                     Text="{Binding NewCoilName, UpdateSourceTrigger=PropertyChanged}" 
                                     Width="200" Margin="0,0,10,0"/>
                <Button Style="{StaticResource ButtonPrimary}" Content="添加线圈" 
                        Command="{Binding AddCoilCommand}" Width="100"/>
                <Button Style="{StaticResource ButtonWarning}" Content="模拟加热一次" 
                        Command="{Binding SimulateHeatingCommand}" Width="120" Margin="10,0,0,0"/>
            </StackPanel>
        </hc:Card>
        <!-- 线圈列表区域 -->
        <hc:Card Grid.Row="1" Header="线圈管理列表">
            <hc:DataGrid ItemsSource="{Binding Coils}" 
                         SelectedItem="{Binding SelectedCoil}"
                         AutoGenerateColumns="False" 
                         hc:DataGridAttach.ShowRowNumber="True"
                         Margin="10">
                <hc:DataGrid.Columns>
                    <!-- 列定义 -->
                    <hc:DataGridTextColumn Header="线圈编号" Binding="{Binding CoilName}" Width="*"/>
                    <hc:DataGridTextColumn Header="剩余次数" Binding="{Binding RemainingCount}" Width="*"/>
                    <!-- 使用 DataBar 直观显示使用率 -->
                    <hc:DataGridTextColumn Header="使用率(%)" Binding="{Binding UsagePercentage, StringFormat=F0}" Width="*"/>
                    <hc:DataGridTemplateColumn Header="状态" Width="100">
                        <hc:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
                                    <hc:ToggleSwitch IsChecked="{Binding IsActive}" IsEnabled="False"/>
                                </StackPanel>
                            </DataTemplate>
                        </hc:DataGridTemplateColumn.CellTemplate>
                    </hc:DataGridTemplateColumn>
                </hc:DataGrid.Columns>
            </hc:DataGrid>
        </hc:Card>
        <!-- 底部操作按钮 -->
        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,20,20">
            <Button Style="{StaticResource ButtonSuccess}" Content="设为激活" 
                    Command="{Binding SetActiveCommand}" Width="100"/>
        </StackPanel>
    </Grid>
</UserControl>

✨ 7. 高级技巧与最佳实践

将图标融入控件

HandyControl支持在其按钮等控件中直接使用矢量图标,这能让你的界面更现代、更精致。你可以从IconExtension类中获取内置图标。

<Button Content="{ext:IconWindow Gear}" Style="{StaticResource ButtonIcon}" />
<hc:Badge Icon="Favorite" />

HandyControl提供了数百个开箱即用的内置图标,如AddDeleteSearchSetting等,直接使用Icon={ext:IconWindow 图标名}即可。

交互反馈

你可以结合Growl通知和Dialog对话框,为用户提供更友好的交互反馈。

try
{
    // 尝试执行操作
    await _coilService.UseOneHeatingAsync();
    Growl.Success("加热完成!");
}
catch (Exception ex)
{
    Growl.Error($"操作失败: {ex.Message}");
}

// 使用 Dialog.Show 进行确认
if (await Dialog.Show("确定要删除这条记录吗?", "警告", 
    button: MessageBoxButton.YesNo, icon: MessageBoxImage.Warning) == MessageBoxResult.Yes)
{
    // 执行删除操作
}

💎 总结

HandyControl几乎可以让你在完全不编写自定义样式的情况下,构建出一个外观专业、交互友好的现代化WPF应用。建议查阅其丰富的官方Demo和文档,其中有超过100个控件的详尽案例,值得继续探索。

另外,“淬火炉监控系统”的项目代码可能比较零散,需要我整理一下,把代码结构和主逻辑重新梳理一下吗?

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐