WPF真入门教程36--真硬核【自动化生产管理平台】

1、超炫颜值

2、项目背景

自动生产管理平台(Automated Production Management Platform)是一种基于现代信息技术(如工业互联网、物联网、大数据、人工智能等)构建的综合性软件系统。

它的核心目标是将传统依赖人工操作和纸质记录的生产管理流程,转变为数字化、智能化和自动化的运行模式。简单来说,就是让工厂的 "大脑"(管理系统)能够自动感知、自动决策、自动调度和自动监控生产过程。

1. 核心功能:它能做什么?

一个成熟的自动生产管理平台通常集成了以下几个关键模块:

  • 生产计划自动排程 (APS)
    • 传统模式:计划员根据经验手工排产,容易出错且难以应对插单、急单。
    • 平台模式:系统根据订单需求、物料库存、设备状态自动计算出最优的生产计划,并自动下发到各个生产单元。
  • 设备联网与数据采集 (SCADA/MES)
    • 传统模式:工人定时去看仪表读数,或设备坏了才发现。
    • 平台模式:平台自动连接 PLC、传感器和机床,实时采集产量、温度、压力、设备故障等数据,无需人工干预。
  • 物料自动配送与仓储 (WMS/AGV)
    • 传统模式:工人推着小车去仓库领料,容易发错料或库存不准。
    • 平台模式:系统根据生产进度,自动指令 AGV(自动导引车)去仓库取货并送到生产线边,同时自动扣减库存。
  • 质量管理自动化 (QMS)
    • 传统模式:人工抽检,填写纸质检验单,事后分析慢。
    • 平台模式:检测设备自动将数据上传平台,系统自动判定合格与否。若发现异常(如尺寸偏差变大),系统可自动触发报警甚至暂停生产线。
  • 能源与能耗管理
    • 自动监控水、电、气的消耗,分析能耗瓶颈,自动优化设备启停时间以节约成本。

2. 关键技术支撑

该平台之所以能 "自动",主要依赖以下技术:

  • 物联网 (IoT):实现物理设备与软件系统的互联互通。
  • 大数据分析:处理海量的生产数据,找出生产规律和瓶颈。
  • 人工智能 (AI):用于预测性维护(预测设备什么时候会坏)、智能排产和质量缺陷图像识别。
  • 数字孪生 (Digital Twin):在电脑上建立一个虚拟的工厂,实时映射现实工厂的运行状态,方便模拟和监控。

3. 带来的价值(为什么要用?)

  • 降本增效:减少了大量的统计员、仓管员和调度员,生产效率显著提升。
  • 质量追溯:产品出了问题,平台可以一键查询出是哪台设备生产的、哪个工人操作的、用了哪批原材料、当时的工艺参数是多少。
  • 柔性生产:能够快速响应市场变化,支持多品种、小批量的混线生产。
  • 透明化管理:老板或管理者在手机或电脑上就能实时看到工厂的每一个角落的实时状态,而不需要去车间。

4. 与传统管理软件的区别

自动生产管理平台 是智能制造(Smart Manufacturing)的核心枢纽。它就像一个智能管家,不仅能帮你记录账目,还能实时指挥机器干活、调配物料、监控质量,并在问题发生前提前预警

3、案例介绍

WPF(Windows Presentation Foundation)是微软推出的桌面应用开发框架,特别适合开发工业场景下的自动化生产管理平台 ------ 它既能满足工业软件对高性能、实时性的要求,又能轻松实现复杂的可视化界面(比如生产看板、设备监控仪表盘)。

一、WPF 开发该平台的核心优势

为什么工业场景首选 WPF 而非 WinForm/Qt?

  1. 强大的可视化能力:支持矢量图形、3D 渲染、自定义控件模板,能轻松做出专业的生产监控大屏、设备状态仪表盘。
  2. 数据绑定与 MVVM 架构:天然适配 MVVM 模式,实现界面与业务逻辑解耦,便于后期维护和功能扩展(工业软件迭代频繁,这点至关重要)。
  3. 高性能与实时性:基于 DirectX 渲染,比 WinForm 更流畅,能高效处理设备实时上报的海量数据(如每秒数百条的设备状态数据)。
  4. 丰富的控件生态:可集成 LiveCharts(图表)、OxyPlot(工控图表)、DevExpress(工业级控件库)等,快速实现工控场景的 UI。
  5. 跨线程处理友好:工业场景中需要频繁从串口 / 网口接收设备数据(子线程),WPF 的 Dispatcher 机制能安全更新 UI,避免界面卡顿。

二、WPF 版自动化生产管理平台核心架构

一个典型的架构分为 4 层,完全遵循 MVVM 设计模式,4 层架构与 MVVM 的对应关系是:设备层(物理层)→ 数据采集层(接口层)→ 业务逻辑层(ViewModel 核心)→ UI 展示层(View 层),其中 MVVM 的 Model 贯穿前三层,是数据载体的核心。以下是每层的详细拆解:

1. 设备层(物理层)
  • 核心定位:平台的 "数据源",是所有生产数据的源头。
  • 关键特性
    • 数据格式不统一(不同设备协议不同:Modbus 寄存器、OPC UA 节点、串口指令);
    • 要求高可靠性(工业设备 7×24 运行,断连需快速检测);
    • 实时性要求(毫秒级数据采集,如设备温度 / 转速)。
  • 与上层交互:仅通过数据采集层提供的通信协议暴露数据,不直接对接业务层
2. 数据采集层(接口层 / Model 层)
  • 核心定位:"数据翻译官",将设备层的异构数据转换为平台统一的 Model 模型。
  • 核心职责 :✅ 设备连接管理(断线重连、心跳检测);✅ 原始数据解析(如 Modbus 寄存器值→温度 / 产量,OPC UA 节点→设备状态);✅ 数据标准化(封装为DeviceRealTimeData/ProductionPlan等 Model);✅ 数据预处理(过滤无效值、补全缺失数据、单位转换)。
3. 业务逻辑层(ViewModel 层)
  • 核心定位:平台的 "大脑",MVVM 的核心层,承上启下。
  • 核心职责 :✅ 订阅采集层的数据更新事件,处理业务规则(如温度 > 35℃触发报警、产量统计);✅ 封装 UI 交互命令(如启动 / 停止采集、下发生产计划、导出报表);✅ 数据持久化(将实时数据写入数据库,供历史查询 / 报表分析);✅ 状态通知(通过INotifyPropertyChanged通知 UI 层更新)。
4. UI 展示层(View 层)
  • 核心定位:"可视化面板",纯展示 + 交互,无任何业务逻辑。
  • 核心职责:✅ 通过数据绑定接收 ViewModel 的状态更新(如设备列表、温度趋势);✅ 提供用户操作入口(按钮 / 输入框),绑定 ViewModel 的命令;✅ 工业级可视化(生产看板、设备仪表盘、报警弹窗)。

核心依赖组件(必选):

  • 数据采集:OpcUaClient(对接工业设备)、Modbus.Device(Modbus 协议)
  • MVVM 框架:Prism/MvvmLight(简化 MVVM 开发)
  • 实时图表:LiveCharts.Wpf(生产数据趋势图)
  • 数据库:SqlSugar/EF Core(对接 SQL Server/MySQL)
  • 异步处理:Task/Async/Await(处理实时数据接收)

数据流向

  • 正向流:设备原始数据 → 采集层标准化 → 业务层处理 → UI 展示;
  • 反向流:用户操作(UI 按钮)→ ViewModel 命令 → 采集层控制设备 → 设备执行动作。

4、技术体系

1)项目技能点

Livechart图表控件,用户控件,自定义控件,MVVM模式,硬件对接,通信协议

2)开发环境

开发工具:Visual Studio 2022

开发语言:C#

UI 框架:WPF

运行时框架:.Net 6.0

设备 :Modbus Slave,Configure Virtual Serial Port Driver

协议:ModbusRtu

依赖:Livechart,NModbus,SerialPort

3)代码展示

cs 复制代码
<Window
    x:Class="West.Automatic.MainWindow"
    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:local="clr-namespace:West.Automatic"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Name="window"
    Title="领航自动化生产管理平台"
    Width="1150"
    Height="750"
    Background="Transparent"
    FontFamily="Microsoft YaHei"
    FontSize="12"
    FontWeight="ExtraLight"
    WindowStartupLocation="CenterScreen"
    mc:Ignorable="d">
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1" />
    </WindowChrome.WindowChrome>
    <Window.Resources>
        <Style x:Key="ControlButtonStyle" TargetType="Button">
            <Setter Property="Width" Value="40" />
            <Setter Property="Background" Value="#11FFFFFF" />
            <Setter Property="Foreground" Value="White" />
            <Setter Property="FontFamily" Value="Assets/Fonts/#iconfont" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid Background="{TemplateBinding Background}">
                            <Border x:Name="root">
                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="root" Property="Background" Value="#33FFFFFF" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>

            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.Background>
            <!--  从中心向外辐射的渐变效果  -->
            <RadialGradientBrush>
                <!--  GradientStops:定义渐变颜色的关键点集合。  -->
                <GradientStop Offset="0" Color="#FF285173" />
                <GradientStop Offset="0.3" Color="#FF244967" />
                <GradientStop Offset="1" Color="#FF14273A" />
            </RadialGradientBrush>
        </Grid.Background>
        <!--  整体分三部分,上部占45,底部占20,其他都给中间  -->
        <Grid.RowDefinitions>
            <RowDefinition Height="45" />
            <RowDefinition />
            <RowDefinition Height="20" />
        </Grid.RowDefinitions>
        <!--  第一行:头部标题布局  -->
        <Border BorderBrush="#5518AABD" BorderThickness="0,0,0,1">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="60" />
                    <ColumnDefinition Width="auto" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <!--  第一列图片  -->
                <Image Margin="10,7" Source="Assets/Images/Logo.png" />
                <!--  第二列文字,采用stackpanel的垂直布局  -->
                <StackPanel Grid.Column="1" VerticalAlignment="Center">
                    <TextBlock
                        FontSize="16"
                        Foreground="White"
                        Text="{Binding Title, ElementName=window}" />
                    <TextBlock
                        Margin="0,2,0,0"
                        FontSize="10"
                        Foreground="LightGray"
                        Text="日月神华 只为财富 领航科技 创造未来" />
                </StackPanel>
                <!--  第三列,分两行,  -->
                <Grid Grid.Column="2">
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition Height="13" />
                    </Grid.RowDefinitions>
                    <!--  第一行放最大最小关闭按钮  -->
                    <Border
                        Width="200"
                        HorizontalAlignment="Right"
                        BorderBrush="Transparent"
                        WindowChrome.IsHitTestVisibleInChrome="True">
                        <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
                            <Button Content="&#xe624;" Style="{StaticResource ControlButtonStyle}" />
                            <Button Content="&#xe600;" Style="{StaticResource ControlButtonStyle}" />
                            <Button
                                Background="DarkRed"
                                Content="&#xe609;"
                                Style="{StaticResource ControlButtonStyle}" Click="Button_Click" />
                        </StackPanel>
                    </Border>
                    <!--  第二行放线条装饰  -->
                    <Border
                        Grid.Row="1"
                        BorderBrush="#5518AABD"
                        BorderThickness="0,1,0,0" />
                    <Border Grid.Row="1" Margin="0,3,0,2">
                        <Border.Background>
                            <VisualBrush
                                TileMode="Tile"
                                Viewport="0,0,7,7"
                                ViewportUnits="Absolute">
                                <VisualBrush.Visual>
                                    <Grid Width="20" Height="20">
                                        <Line
                                            Stroke="Gray"
                                            StrokeThickness="1"
                                            X1="0"
                                            X2="10"
                                            Y1="10"
                                            Y2="0" />
                                    </Grid>
                                </VisualBrush.Visual>
                            </VisualBrush>
                        </Border.Background>
                    </Border>
                </Grid>


            </Grid>
        </Border>

        <!--  第二行:内容部分  -->
        <ContentControl Grid.Row="1" Content="{Binding PageContent}" />

        <!--  第三行:状态栏  -->
        <Border
            Grid.Row="2"
            BorderBrush="#5518AABD"
            BorderThickness="0,1,0,0">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition Width="auto" />
                </Grid.ColumnDefinitions>
                <Border Grid.Row="0" Margin="0,5">
                    <Border.Background>
                        <VisualBrush
                            TileMode="Tile"
                            Viewport="0,0,7,7"
                            ViewportUnits="Absolute">
                            <VisualBrush.Visual>
                                <Grid Width="20" Height="20">
                                    <Line
                                        Stroke="Gray"
                                        StrokeThickness="1"
                                        X1="0"
                                        X2="10"
                                        Y1="10"
                                        Y2="0" />
                                </Grid>
                            </VisualBrush.Visual>
                        </VisualBrush>
                    </Border.Background>
                </Border>
                <TextBlock
                    Grid.Column="1"
                    Margin="10,1"
                    VerticalAlignment="Center"
                    FontSize="11"
                    FontWeight="Bold"
                    Foreground="White"
                    Text="2026 北京领航智能科技有限公司 Co.Ltd" />
            </Grid>
        </Border>

    </Grid>
</Window>
cs 复制代码
<UserControl
    x:Class="West.Automatic.Views.MonitorView"
    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:local="clr-namespace:West.Automatic.Views"
    xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:zxc="clr-namespace:West.Automatic.Controls"
    d:DesignHeight="450"
    d:DesignWidth="1100"
    mc:Ignorable="d">
    <UserControl.Resources>
        <!--  作用于groupbox控件的样式  -->
        <Style TargetType="GroupBox">
            <Setter Property="Margin" Value="10,5" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="GroupBox">
                        <Grid>
                            <Polyline
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                Points="0 30,0 10,10 0,30 0"
                                Stroke="#9918AABD"
                                StrokeThickness="1" />
                            <Ellipse
                                Width="4"
                                Height="4"
                                Margin="24,-2,0,0"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                Fill="#9918AABD" />
                            <Ellipse
                                Width="4"
                                Height="4"
                                Margin="-2,24,0,0"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                Fill="#9918AABD" />
                            <Path
                                HorizontalAlignment="Right"
                                VerticalAlignment="Top"
                                Data="M0 0,3 3,30 3,33 0,68 0,73 7,78 7,78 10M8 0,25 0"
                                Stroke="#5518AABD" />
                            <Polyline
                                HorizontalAlignment="Left"
                                VerticalAlignment="Bottom"
                                Points="0,0 0,15 10,15"
                                Stroke="#5518AABD" />
                            <Polyline
                                HorizontalAlignment="Right"
                                VerticalAlignment="Bottom"
                                Points="10,0 0,10"
                                Stroke="#5518AABD" />
                            <Polygon
                                HorizontalAlignment="Right"
                                VerticalAlignment="Bottom"
                                Fill="#9918AABD"
                                Points="0,7 7 7 7 0" />
                            <Border
                                Margin="30,-0.5,78,0"
                                VerticalAlignment="Top"
                                BorderBrush="#5518AABD"
                                BorderThickness="0,1,0,0" />
                            <Border
                                Margin="0,10"
                                HorizontalAlignment="Right"
                                BorderBrush="#5518AABD"
                                BorderThickness="0,0,1,0" />
                            <Border
                                Margin="10,0"
                                VerticalAlignment="Bottom"
                                BorderBrush="#5518AABD"
                                BorderThickness="0,1,0,0" />
                            <Border
                                Margin="-0.5,15"
                                HorizontalAlignment="Left"
                                BorderBrush="#5518AABD"
                                BorderThickness="0,0,1,0" />
                            <Path
                                Margin="10,13"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                Data="M0 0,3 0,5 4,3 8,0 8,3 4"
                                Fill="#9918AABD" />
                            <Path
                                Margin="16,13"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                Data="M0 0,3 0,5 4,3 8,0 8,3 4"
                                Fill="#5518AABD" />
                            <TextBlock
                                Margin="25,8"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                Foreground="#99FFFFFF"
                                Text="{TemplateBinding Header}" />
                            <ContentPresenter />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>
    <Grid>
        <!--  整体分三行,上面占50,下面占120,其他给中间  -->
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition />
            <RowDefinition Height="120" />
        </Grid.RowDefinitions>

        <!--  第一行布局,分两列  -->
        <!--  第一行  -->
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <StackPanel
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Orientation="Horizontal">
                <TextBlock
                    VerticalAlignment="Center"
                    FontFamily="../Assets/Fonts/#digital_display"
                    FontSize="30"
                    Foreground="White"
                    Text="20:00" />
                <StackPanel
                    Margin="15,0,0,0"
                    TextBlock.FontSize="10"
                    TextBlock.Foreground="White">
                    <TextBlock Text="2022-07-05" />
                    <TextBlock HorizontalAlignment="Right" Text="星期五" />
                </StackPanel>
            </StackPanel>
            <!--  计数  -->
            <StackPanel
                Grid.Column="1"
                Margin="20,0,0,0"
                HorizontalAlignment="Left"
                VerticalAlignment="Center"
                Orientation="Horizontal">
                <!--  定义资源,用于ItemsControl的数据模板  -->
                <StackPanel.Resources>
                    <DataTemplate x:Key="dataTemp">
                        <Border
                            Width="15"
                            Margin="2,0"
                            Background="#3318AABD">
                            <TextBlock
                                HorizontalAlignment="left"
                                VerticalAlignment="Center"
                                FontSize="16"
                                FontWeight="Normal"
                                Foreground="White"
                                Text="{Binding}" />
                        </Border>
                    </DataTemplate>
                </StackPanel.Resources>
                <!--  图标  -->
                <TextBlock
                    VerticalAlignment="Center"
                    FontFamily="../Assets/Fonts/#iconfont"
                    FontSize="20"
                    Foreground="#55FFFFFF"
                    Text="&#xe661;" />
                <!--  机台总数  -->
                <TextBlock
                    Margin="10,0"
                    VerticalAlignment="Center"
                    FontSize="10"
                    Foreground="#99FFFFFF"
                    Text="机台&#13;总数" />
                <ItemsControl ItemTemplate="{StaticResource dataTemp}" ItemsSource="{Binding Total}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <VirtualizingStackPanel Orientation="Horizontal" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
                <!--  生产计数  -->
                <TextBlock
                    Margin="20,0,10,0"
                    VerticalAlignment="Center"
                    Foreground="#99FFFFFF"
                    Text="生产计数" />
                <ItemsControl ItemTemplate="{StaticResource dataTemp}" ItemsSource="{Binding ProductionCount}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <VirtualizingStackPanel Orientation="Horizontal" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
                <!--  不良计数  -->
                <TextBlock
                    Margin="20,0,10,0"
                    VerticalAlignment="Center"
                    Foreground="#99FFFFFF"
                    Text="不良计数" />
                <ItemsControl ItemTemplate="{StaticResource dataTemp}" ItemsSource="{Binding BadCount}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <VirtualizingStackPanel Orientation="Horizontal" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </StackPanel>
            <!--  配置按钮  -->
            <Button
                Grid.Column="1"
                Width="80"
                Height="33"
                Margin="20,0"
                HorizontalAlignment="Right"
                VerticalAlignment="Center"
                Command="{Binding SettingsCommand, RelativeSource={RelativeSource AncestorType=Window}}"
                Content="配置"
                Style="{StaticResource ButtonStyle}"
                Tag="&#xe625;" />
        </Grid>

        <!--  第二行布局,分三列  -->
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <!--  第1列包含3个groupbox:环境,产能,质量  -->
            <UniformGrid
                Grid.Column="0"
                Margin="10,0"
                Columns="1">
                <!--  环境面板  -->
                <GroupBox Header="环境">
                    <ItemsControl VerticalAlignment="Center" ItemsSource="{Binding Evironment}">
                        <!--  面板模板  -->
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <UniformGrid Columns="4" />
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <!--  项模板  -->
                        <ItemsControl.ItemTemplate>
                            <!--  数据模板  -->
                            <DataTemplate>
                                <StackPanel
                                    Margin="0,5"
                                    HorizontalAlignment="Center"
                                    VerticalAlignment="Center">
                                    <TextBlock
                                        Margin="0,5"
                                        HorizontalAlignment="Center"
                                        FontSize="16"
                                        Foreground="#FF2BEDF1"
                                        Text="{Binding Value}" />
                                    <TextBlock
                                        FontSize="10"
                                        Foreground="#AAFFFFFF"
                                        Text="{Binding Header}" />
                                </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </GroupBox>

                <!--  产能面板:柱状图  -->
                <GroupBox Header="产能">
                    <Grid>
                        <lvc:CartesianChart Margin="20,35,20,5">
                            <!--  序列部分:包含2个序列(生产计数和不良计数)  -->
                            <lvc:CartesianChart.Series>
                                <lvc:ColumnSeries
                                    Title="生产计数"
                                    MaxColumnWidth="10"
                                    Values="300,400,480,450,380,450,450,330,340,280,220">
                                    <lvc:ColumnSeries.Fill>
                                        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                            <GradientStop Offset="0" Color="#FF3FBBE6" />
                                            <GradientStop Offset="1" Color="#FF2BEDF1" />
                                        </LinearGradientBrush>
                                    </lvc:ColumnSeries.Fill>
                                </lvc:ColumnSeries>
                                <lvc:ColumnSeries
                                    Title="不良计数"
                                    MaxColumnWidth="10"
                                    Values="15,55,15,40,38,45,25,15">
                                    <lvc:ColumnSeries.Fill>
                                        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                            <GradientStop Offset="0" Color="#FFFB9A9A" />
                                            <GradientStop Offset="1" Color="#FFFF5151" />
                                        </LinearGradientBrush>
                                    </lvc:ColumnSeries.Fill>
                                </lvc:ColumnSeries>
                            </lvc:CartesianChart.Series>
                            <!--  X轴数据  -->
                            <lvc:CartesianChart.AxisX>
                                <lvc:Axis Labels="8:00,9:00,10:00,11:00,12:00,13:00,14:00,15:00,16:00,17:00,18:00">
                                    <lvc:Axis.Separator>
                                        <lvc:Separator Step="1" StrokeThickness="0" />
                                    </lvc:Axis.Separator>
                                </lvc:Axis>
                            </lvc:CartesianChart.AxisX>
                            <!--  Y轴数据  -->
                            <lvc:CartesianChart.AxisY>
                                <lvc:Axis MaxValue="500" MinValue="0">
                                    <lvc:Axis.Separator>
                                        <lvc:Separator Step="100" Stroke="#11FFFFFF" />
                                    </lvc:Axis.Separator>
                                </lvc:Axis>
                            </lvc:CartesianChart.AxisY>
                        </lvc:CartesianChart>
                        <StackPanel
                            Margin="10"
                            HorizontalAlignment="Right"
                            VerticalAlignment="Top"
                            Orientation="Horizontal">
                            <Border
                                Width="6"
                                Height="6"
                                Margin="5,0"
                                Background="#FF2BEDF1" />
                            <TextBlock
                                FontSize="10"
                                Foreground="#44FFFFFF"
                                Text="生产计数" />
                            <Border
                                Width="6"
                                Height="6"
                                Margin="5,0"
                                Background="#FFFF5151" />
                            <TextBlock
                                FontSize="10"
                                Foreground="#44FFFFFF"
                                Text="不良计数" />
                        </StackPanel>
                    </Grid>
                </GroupBox>

                <!--  质量面板:拆线图  -->
                <GroupBox Header="质量">
                    <lvc:CartesianChart Margin="20,35,20,5">
                        <!--  序列部分  -->
                        <lvc:CartesianChart.Series>
                            <lvc:LineSeries
                                Title="不良计数"
                                PointGeometrySize="0"
                                Stroke="#FF2BEDF1"
                                StrokeThickness="1"
                                Values="15,55,15,40,38,45,25,15,45,25,15,49">
                                <lvc:LineSeries.Fill>
                                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                        <GradientStop Offset="0" Color="#552BEDF1" />
                                        <GradientStop Offset="1" Color="Transparent" />
                                    </LinearGradientBrush>
                                </lvc:LineSeries.Fill>
                            </lvc:LineSeries>
                        </lvc:CartesianChart.Series>
                        <!--  X轴数据  -->
                        <lvc:CartesianChart.AxisX>
                            <lvc:Axis Labels="8:00,9:00,10:00,11:00,12:00,13:00,14:00,15:00,16:00,17:00,18:00">
                                <lvc:Axis.Separator>
                                    <lvc:Separator Step="1" StrokeThickness="0" />
                                </lvc:Axis.Separator>
                            </lvc:Axis>
                        </lvc:CartesianChart.AxisX>
                        <!--  Y轴数据  -->
                        <lvc:CartesianChart.AxisY>
                            <lvc:Axis MaxValue="100" MinValue="0">
                                <lvc:Axis.Separator>
                                    <lvc:Separator Step="20" Stroke="#11FFFFFF" />
                                </lvc:Axis.Separator>
                            </lvc:Axis>
                        </lvc:CartesianChart.AxisY>
                    </lvc:CartesianChart>
                </GroupBox>
            </UniformGrid>

            <!--  第2列包含3个内容  -->
            <Grid Grid.Column="1">
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition Height="120" />
                    <RowDefinition Height="1.5*" />
                </Grid.RowDefinitions>
                <!--  第1行放边框  -->
                <Border
                    Grid.RowSpan="2"
                    Width="400"
                    Height="150"
                    HorizontalAlignment="Right"
                    VerticalAlignment="Top">
                    <Border.Background>
                        <ImageBrush ImageSource="../Assets/Images/device.png" Stretch="Uniform" />
                    </Border.Background>
                </Border>

                <!--  第2行放报警记录:数据列表  -->
                <Grid Grid.Row="1">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30" />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <TextBlock
                        HorizontalAlignment="Left"
                        VerticalAlignment="Center"
                        FontWeight="Normal"
                        Foreground="#99FFFFFF">
                        <Run FontFamily="../Assets/Fonts/#iconfont" Text="&#xe68d;" />
                        <Run Text="报警记录" />
                    </TextBlock>
                    <ItemsControl Grid.Row="1" ItemsSource="{Binding AlarmList}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Grid Height="23">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="20" />
                                        <ColumnDefinition Width="30" />
                                        <ColumnDefinition Width="1.3*" />
                                        <ColumnDefinition />
                                        <ColumnDefinition Width="0.5*" />
                                    </Grid.ColumnDefinitions>
                                    <Border
                                        Width="6"
                                        Height="6"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        Background="IndianRed"
                                        CornerRadius="3" />
                                    <TextBlock
                                        Grid.Column="1"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        FontWeight="Normal"
                                        Foreground="#992BEDF1"
                                        Text="{Binding Num}" />
                                    <TextBlock
                                        Grid.Column="2"
                                        VerticalAlignment="Center"
                                        FontWeight="Normal"
                                        Foreground="#992BEDF1"
                                        Text="{Binding Message}" />
                                    <TextBlock
                                        Grid.Column="3"
                                        VerticalAlignment="Center"
                                        FontWeight="Normal"
                                        Foreground="#992BEDF1"
                                        Text="{Binding Time}" />
                                    <TextBlock
                                        Grid.Column="4"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        FontWeight="Normal"
                                        Foreground="#992BEDF1"
                                        Text="{Binding Duration, StringFormat=时长{0}秒}" />
                                </Grid>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </Grid>

                <!--  第3行放报警比率:饼状图  -->
                <GroupBox
                    Grid.Row="2"
                    Margin="0,5"
                    Header="数据异常报警比率">
                    <lvc:PieChart Margin="0,40,0,20" InnerRadius="45">
                        <lvc:PieChart.Resources>
                            <Style TargetType="lvc:PieSeries">
                                <Setter Property="DataLabelsTemplate">
                                    <Setter.Value>
                                        <!--  数据模板  -->
                                        <DataTemplate>
                                            <StackPanel Orientation="Horizontal" TextBlock.Foreground="#44FFFFFF">
                                                <!--  绑定标签文字  -->
                                                <TextBlock Margin="0,0,5,0" Text="{Binding Point.SeriesView.Title}" />
                                                <!--  绑定序列的值  -->
                                                <TextBlock Text="{Binding Point.SeriesView.Values[0]}" />
                                            </StackPanel>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </lvc:PieChart.Resources>
                        <!--  数据序列  -->
                        <lvc:PieChart.Series>
                            <lvc:PieSeries
                                Title="颜色"
                                DataLabels="True"
                                LabelPosition="OutsideSlice"
                                StrokeThickness="0"
                                Values="24" />
                            <lvc:PieSeries
                                Title="光照"
                                DataLabels="True"
                                LabelPosition="OutsideSlice"
                                StrokeThickness="0"
                                Values="30" />
                            <lvc:PieSeries
                                Title="温度"
                                DataLabels="True"
                                LabelPosition="OutsideSlice"
                                StrokeThickness="0"
                                Values="10" />
                            <lvc:PieSeries
                                Title="振动"
                                DataLabels="True"
                                LabelPosition="OutsideSlice"
                                StrokeThickness="0"
                                Values="40" />
                            <lvc:PieSeries
                                Title="压差"
                                DataLabels="True"
                                LabelPosition="OutsideSlice"
                                StrokeThickness="0"
                                Values="27" />
                            <lvc:PieSeries
                                Title="力差"
                                DataLabels="True"
                                LabelPosition="OutsideSlice"
                                StrokeThickness="0"
                                Values="45" />
                            <lvc:PieSeries
                                Title="溶度"
                                DataLabels="True"
                                LabelPosition="OutsideSlice"
                                StrokeThickness="0"
                                Values="20" />
                            <lvc:PieSeries
                                Title="角度"
                                DataLabels="True"
                                LabelPosition="OutsideSlice"
                                StrokeThickness="0"
                                Values="16" />
                            <lvc:PieSeries
                                Title="压差"
                                DataLabels="True"
                                LabelPosition="OutsideSlice"
                                StrokeThickness="0"
                                Values="25" />
                        </lvc:PieChart.Series>
                    </lvc:PieChart>
                </GroupBox>
            </Grid>

            <!--  第3列包含3个groupbox  -->
            <UniformGrid
                Grid.Column="2"
                Margin="10,0"
                Columns="1">
                <!--  设备数据列表  -->
                <GroupBox Header="设备">
                    <ItemsControl VerticalAlignment="Center" ItemsSource="{Binding DeviceMonitor}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <!--  设置表格有4列  -->
                                <UniformGrid Columns="4" />
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <StackPanel
                                    Margin="0,5"
                                    HorizontalAlignment="Center"
                                    VerticalAlignment="Center">
                                    <TextBlock
                                        Margin="0,5"
                                        HorizontalAlignment="Center"
                                        FontSize="16"
                                        Foreground="#FF2BEDF1"
                                        Text="{Binding Value}" />
                                    <TextBlock
                                        FontSize="10"
                                        Foreground="#AAFFFFFF"
                                        Text="{Binding Header}" />
                                </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </GroupBox>

                <!--  能耗数据,使用用户控件来呈现  -->
                <GroupBox Header="能耗">
                    <zxc:RaderChart ItemsSources="{Binding RaderDatas}" />
                </GroupBox>

                <GroupBox Header="人力">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition />
                            <ColumnDefinition Width="1.8*" />
                        </Grid.ColumnDefinitions>
                        <!--  第1列内容,垂直放2个文本  -->
                        <StackPanel
                            Grid.Column="0"
                            Margin="0,20,0,0"
                            VerticalAlignment="Center">
                            <TextBlock
                                HorizontalAlignment="Center"
                                FontSize="25"
                                Foreground="#99FFFFFF"
                                Text="1600" />
                            <TextBlock
                                Margin="0,5"
                                HorizontalAlignment="Center"
                                FontSize="12"
                                Foreground="#55FFFFFF"
                                Text="在职在岗" />
                        </StackPanel>
                        <!--  第2列内容,放文字和ItemControl  -->
                        <Grid Grid.Column="1">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="30" />
                                <RowDefinition />
                            </Grid.RowDefinitions>
                            <TextBlock
                                VerticalAlignment="Center"
                                Foreground="#18AABD"
                                Text="缺岗统计" />
                            <!--  数据列表  -->
                            <ItemsControl Grid.Row="1" ItemsSource="{Binding PersonnelList}">
                                <ItemsControl.ItemTemplate>
                                    <!--  数据模板,定义4列,分别绑定集合中对象的各个属性  -->
                                    <DataTemplate>
                                        <Grid Height="20">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="10" />
                                                <ColumnDefinition Width="50" />
                                                <ColumnDefinition Width="40" />
                                                <ColumnDefinition />
                                            </Grid.ColumnDefinitions>
                                            <Border
                                                Width="5"
                                                Height="5"
                                                Background="Orange"
                                                CornerRadius="5" />
                                            <TextBlock
                                                Grid.Column="1"
                                                HorizontalAlignment="Center"
                                                VerticalAlignment="Center"
                                                FontSize="11"
                                                Foreground="#99FFFFFF"
                                                Text="{Binding Name}" />
                                            <TextBlock
                                                Grid.Column="2"
                                                HorizontalAlignment="Center"
                                                VerticalAlignment="Center"
                                                FontSize="11"
                                                Foreground="#99FFFFFF"
                                                Text="{Binding Duties}" />
                                            <StackPanel Grid.Column="3" Orientation="Horizontal">
                                                <Border
                                                    Width="70"
                                                    Height="3"
                                                    Margin="5,0"
                                                    Background="#AA2BEDF1" />
                                                <TextBlock
                                                    VerticalAlignment="Center"
                                                    FontSize="9"
                                                    Foreground="#99FFFFFF"
                                                    Text="{Binding ManHour}" />
                                            </StackPanel>
                                        </Grid>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </Grid>
                    </Grid>
                </GroupBox>
            </UniformGrid>

        </Grid>

        <!--  第三行,放itemcontrol  -->
        <ItemsControl
            Grid.Row="2"
            Margin="10,0"
            ItemsSource="{Binding WorkshopList}">
            <!--  面板模板  -->
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Rows="1" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <!--  数据模板  -->
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <!--  所有数据放在一个边框内  -->
                    <Border
                        Margin="10,5"
                        Background="#0A18AABD"
                        BorderBrush="#9918AABD"
                        BorderThickness="0,1,0,0">
                        <Grid>
                            <!--  分2行2列  -->
                            <Grid.RowDefinitions>
                                <RowDefinition Height="30" />
                                <RowDefinition />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="90" />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <!--  第一行放名称和详情按钮  -->
                            <TextBlock
                                Margin="10,0"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Center"
                                Foreground="#18AABD"
                                Text="{Binding Name}" />
                            <TextBlock
                                Grid.Column="1"
                                Margin="10,0"
                                HorizontalAlignment="Right"
                                VerticalAlignment="Center">
                                <Hyperlink
                                    Command="{Binding DetailCommand, RelativeSource={RelativeSource AncestorType=Window}}"
                                    CommandParameter="{Binding}"
                                    Foreground="#33FFFFFF"
                                    TextDecorations="None">
                                    [ 详情 ]
                                </Hyperlink>
                            </TextBlock>

                            <!--  第二行放机台总数和UniformGrid  -->
                            <StackPanel
                                Grid.Row="1"
                                Grid.Column="0"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center">
                                <TextBlock
                                    FontSize="10"
                                    Foreground="#55FFFFFF"
                                    Text="机台总数" />
                                <TextBlock
                                    Margin="0,5"
                                    HorizontalAlignment="Center"
                                    FontSize="30"
                                    Foreground="#99FFFFFF"
                                    Text="{Binding TotalCount}" />
                            </StackPanel>

                            <UniformGrid Grid.Row="1" Grid.Column="1">
                                <StackPanel>
                                    <TextBlock
                                        HorizontalAlignment="Center"
                                        FontSize="16"
                                        FontWeight="Normal"
                                        Foreground="LightSeaGreen"
                                        Text="{Binding WorkCount}" />
                                    <TextBlock
                                        HorizontalAlignment="Center"
                                        FontSize="10"
                                        Foreground="#55FFFFFF"
                                        Text="作业" />
                                </StackPanel>
                                <StackPanel>
                                    <TextBlock
                                        HorizontalAlignment="Center"
                                        FontSize="16"
                                        FontWeight="Normal"
                                        Foreground="DarkOrange"
                                        Text="{Binding WaitCount}" />
                                    <TextBlock
                                        HorizontalAlignment="Center"
                                        Foreground="#55FFFFFF"
                                        Text="等待" />
                                </StackPanel>
                                <StackPanel>
                                    <TextBlock
                                        HorizontalAlignment="Center"
                                        FontSize="16"
                                        FontWeight="Normal"
                                        Foreground="DarkRed"
                                        Text="{Binding FaultCount}" />
                                    <TextBlock
                                        HorizontalAlignment="Center"
                                        Foreground="#55FFFFFF"
                                        Text="故障" />
                                </StackPanel>
                                <StackPanel>
                                    <TextBlock
                                        HorizontalAlignment="Center"
                                        FontSize="16"
                                        FontWeight="Normal"
                                        Foreground="Gray"
                                        Text="{Binding StopCount}" />
                                    <TextBlock
                                        HorizontalAlignment="Center"
                                        Foreground="#55FFFFFF"
                                        Text="停机" />
                                </StackPanel>
                            </UniformGrid>
                        </Grid>

                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

    </Grid>
</UserControl>

5、超大礼包

6、小结

  • WPF 是工业自动化生产管理平台的优选框架:核心优势是可视化能力强、MVVM 解耦、实时性高,适配工业场景的复杂 UI 和数据处理需求。
  • 核心架构遵循 MVVM:设备数据采集层(Modbus/OPC UA)→ 业务逻辑层(ViewModel)→ UI 展示层(View),便于维护和扩展。
  • 关键实现要点:异步采集设备数据、线程安全更新 UI、数据可视化(图表)、状态实时监控,示例代码可直接落地并扩展为完整平台。
复制代码
原创不易,打字不易,截图不易,撸码不易,整理不易,走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,灌水,请动动你的金手指,祝您早日实现财务自由。
相关推荐
七夜zippoe8 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
Fcy64810 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满10 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠10 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
Harvey90310 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
珠海西格电力科技11 小时前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
释怀不想释怀12 小时前
Linux环境变量
linux·运维·服务器
zzzsde12 小时前
【Linux】进程(4):进程优先级&&调度队列
linux·运维·服务器
聆风吟º13 小时前
CANN开源项目实战指南:使用oam-tools构建自动化故障诊断与运维可观测性体系
运维·开源·自动化·cann
NPE~14 小时前
自动化工具Drissonpage 保姆级教程(含xpath语法)
运维·后端·爬虫·自动化·网络爬虫·xpath·浏览器自动化