当前位置: 首页 > article >正文

WPF+MVVM案例实战(三)- 动态数字卡片效果实现

1、创建项目

打开 VS2022 ,新建项目 Wpf_Examples,创建各层级文件夹,安装 CommunityToolkit.Mvvm 和 Microsoft.Extensions.DependencyInjectio NuGet包,完成MVVM框架搭建。搭建完成后项目层次如下图所示:
在这里插入图片描述
这里如何实现 MVVM 框架可以参考本人 像 MvvmLight 一样使用 CommunityToolkit.Mvvm 工具包 的文章

2、整理项目

1、项目目录层级

在前面该案例前,已经发布了两个案例,为了后续不断推出的新案例,我们先将项目整理成一个整体,做成整套案例系统,后续所有的案例都在该项目上迭代更新。目前先做简单的归纳处理,我们把所有案例都单独放在一个窗体,主窗体做按钮菜单,每个案例通过弹窗方式呈现。基于以上整理后得到系统文件层级分布如下所示:

在这里插入图片描述

2、案例代码实现

1、主界面菜单实现

1、MainWindow.xaml 代码
<Window x:Class="Wpf_Examples.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:converter="clr-namespace:Wpf_Examples.Converters"
        xmlns:local="clr-namespace:Wpf_Examples"
        xmlns:cc="clr-namespace:CustomControlLib;assembly=CustomControlLib"
        DataContext="{Binding Source={StaticResource Locator},Path=Main}"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <WrapPanel>
            <Button Width="120" Height="30" FontSize="18" Content="图片按钮" Command="{Binding ButtonClickCmd}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self},Path=Content}" Margin="8"/>
            <Button Width="120" Height="30" FontSize="18" Content="LED效果灯" Command="{Binding ButtonClickCmd}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self},Path=Content}" Margin="8"/>
            <Button Width="120" Height="30" FontSize="18" Content="动态数字卡" Command="{Binding ButtonClickCmd}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self},Path=Content}" Margin="8"/>
        </WrapPanel>
    </Grid>
</Window>

2、MainViewWindow. 代码
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Wpf_Examples.Views;

namespace Wpf_Examples.ViewModels
{
    public class MainViewModel : ObservableObject
    {


        public RelayCommand<string> ButtonClickCmd { get; set; }
        public MainViewModel()
        {
            ButtonClickCmd = new RelayCommand<string>(FunMenu);
        }

        private void FunMenu(string obj)
        {
            switch (obj)
            {
                case "图片按钮":
                    PopWindow(new ImageButtonWindow());
                    break;
                case "LED效果灯":
                    PopWindow(new LEDStatusWindow());
                    break;
                case "动态数字卡":
                    PopWindow(new DataCardWindow());
                    break;

            }
        }

        private void PopWindow(Window window)
        {
            var mainWindowInstance = App.Current.MainWindow; // 获取主窗口实例
            window.Owner = mainWindowInstance;
            window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            window.ShowDialog();
        }
    }
}

3、界面效果

在这里插入图片描述

2、案例一 图片按钮整理实现

1、ImageButtonWindow.xaml 代码
<Window x:Class="Wpf_Examples.Views.ImageButtonWindow"
        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"
        xmlns:cc="clr-namespace:CustomControlLib;assembly=CustomControlLib"
        xmlns:converter="clr-namespace:Wpf_Examples.Converters"
        xmlns:local="clr-namespace:Wpf_Examples.Views"
        DataContext="{Binding Source={StaticResource Locator},Path=ImageButton}"
        mc:Ignorable="d"
        Title="ImageButtonWindow" Height="450" Width="800">
    <Window.Resources>
        <converter:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center"  HorizontalAlignment="Right">
            <TextBlock Text="双按钮状态控制,边框同时虚线实线切换" FontSize="30" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0 0 80 0"/>
            <cc:ImageTextButton Text="开始生产" ToolTip="开始生产"  IsDashedBorder="{Binding SystemStatus}" Command="{Binding ButtonClickCmd}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self},Path=ToolTip}" Width="70" Height="70" Margin="0,0,5,0" ImageSource="pack://application:,,,/Wpf_Examples;component/Assets/Images/Start.png"/>
            <cc:ImageTextButton Text="停止生产" ToolTip="停止生产"   IsDashedBorder="{Binding SystemStatus,Converter={StaticResource InverseBooleanConverter}}" Command="{Binding ButtonClickCmd}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self},Path=ToolTip}" Width="70" Height="70" Margin="0,0,5,0" ImageSource="pack://application:,,,/Wpf_Examples;component/Assets/Images/Stop.png"/>
        </StackPanel>

        <StackPanel Orientation="Horizontal" VerticalAlignment="Center"  HorizontalAlignment="Right" Grid.Row="1">
            <TextBlock Text="单按钮状态控制,切换背景图片和文本" FontSize="30" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0 0 80 0"/>
            <cc:ImageTextButton Text="{Binding ButtonName}" Command="{Binding SingleButtonClickCmd}" ImageSource="{Binding ImageSource}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self},Path=Text}" Width="70" Height="70" Margin="0,0,5,0" />
        </StackPanel>
    </Grid>
</Window>

2、ImageButtonViewModel.cs 代码
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;

namespace Wpf_Examples.ViewModels
{
    public class ImageButtonViewModel:ObservableObject
    {

        /// <summary>
        /// 生产状态按钮名称
        /// </summary>
        private string buttonName;
        public string ButtonName
        {
            get { return buttonName; }
            set { SetProperty(ref buttonName, value); }
        }

        /// <summary>
        /// 系统运行状态
        /// </summary>
        private bool systemStatus = false;
        public bool SystemStatus
        {
            get { return systemStatus; }
            set { SetProperty(ref systemStatus, value); }
        }
        /// <summary>
        /// 产线状态
        /// </summary>
        private bool productStatus = false;
        public bool ProductStatus
        {
            get { return productStatus; }
            set { SetProperty(ref productStatus, value); }
        }


        /// <summary>
        /// 生产状态背景图
        /// </summary>
        private BitmapImage imageSource;
        public BitmapImage ImageSource
        {
            get { return imageSource; }
            set { SetProperty(ref imageSource, value); }
        }

        public RelayCommand SingleButtonClickCmd { get; set; }
        public RelayCommand<string> ButtonClickCmd { get; set; }
        public ImageButtonViewModel()
        {
            SingleButtonClickCmd = new RelayCommand(StatusChange);
            ButtonClickCmd = new RelayCommand<string>(FunMenu);
            StatusChange();
        }

      private void FunMenu(string obj)
 {
     switch (obj)
     {
         case "开始生产":
             SystemStatus = true;
             break;
         case "停止生产":
             SystemStatus = false;
             break;
     }
 }

        private void StatusChange()
        {
            if (!ProductStatus)
            {
                ButtonName = "开始生产";
                ImageSource = new BitmapImage(new Uri("pack://application:,,,/Wpf_Examples;component/Assets/Images/Start.png"));
                ProductStatus = true;
            }
            else
            {
                ButtonName = "停止生产";
                ImageSource = new BitmapImage(new Uri("pack://application:,,,/Wpf_Examples;component/Assets/Images/Stop.png"));
                ProductStatus = false;
            }

        }
    }
}

3、InverseBooleanConverter.cs 转换器代码
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace Wpf_Examples.Converters
{
    public class InverseBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !(value is bool boolValue) || !boolValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !(value is bool boolValue) || !boolValue;
        }
    }
}

3、案例二 LED灯整理实现

1、LEDStatusWindow.xaml 代码
<Window x:Class="Wpf_Examples.Views.LEDStatusWindow"
        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"
        xmlns:converter="clr-namespace:Wpf_Examples.Converters"
        xmlns:local="clr-namespace:Wpf_Examples.Views"
        DataContext="{Binding Source={StaticResource Locator},Path=LedStatus}"
        mc:Ignorable="d"
        Title="LEDStatusWindow" Height="450" Width="800">
    <Window.Resources>
        <converter:StatusToColorConverter x:Key="StatusToColorConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Right" >
            <TextBlock Text="网络" FontSize="16" Foreground="DarkGray" Margin="0 0 20 0"/>
            <Ellipse Width="20" Height="20" Fill="{Binding NetStatusValue, Converter={StaticResource StatusToColorConverter}}"/>
        </StackPanel>
        <StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
            <TextBlock Text="PLC" FontSize="16" Foreground="DarkGray" Margin="0 0 20 0"/>
            <Ellipse Width="20" Height="20" Fill="{Binding PLCStatusValue, Converter={StaticResource StatusToColorConverter}}"/>
        </StackPanel>
        <StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left">
            <TextBlock Text="相机" FontSize="16" Foreground="DarkGray" Margin="0 0 20 0"/>
            <Ellipse Width="20" Height="20" Fill="{Binding DevStatusValue, Converter={StaticResource StatusToColorConverter}}"/>
        </StackPanel>
    </Grid>
</Window>

2、LEDStatusViewModel.cs 代码
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace Wpf_Examples.ViewModels
{
    public class LEDStatusViewModel: ObservableObject
    {

        /// <summary>
        /// 网络状态按钮名称
        /// </summary>
        private int netStatusValue = 2;
        public int NetStatusValue
        {
            get { return netStatusValue; }
            set { SetProperty(ref netStatusValue, value); }
        }
        /// <summary>
        /// PLC状态按钮名称
        /// </summary>
        private int plcStatusValue = 1;
        public int PLCStatusValue
        {
            get { return plcStatusValue; }
            set { SetProperty(ref plcStatusValue, value); }
        }
        /// <summary>
        /// 设备状态
        /// </summary>
        private int devStatusValue = 0;
        public int DevStatusValue
        {
            get { return devStatusValue; }
            set { SetProperty(ref devStatusValue, value); }
        }

        /// <summary>
        /// 系统运行状态
        /// </summary>
        private bool systemStatus = false;
        public bool SystemStatus
        {
            get { return systemStatus; }
            set { SetProperty(ref systemStatus, value); }
        }

       
        public LEDStatusViewModel()
        {
          
            CreateTimer();
        }

       
        private void DispatcherTimer_Tick(object sender, EventArgs e)
        {

            DevStatusValue = StatusChange(DevStatusValue);
            NetStatusValue = StatusChange(NetStatusValue);
            PLCStatusValue = StatusChange(PLCStatusValue);
        }

        private void CreateTimer()
        {
            #region 每秒定时器服务
            DispatcherTimer cpuTimer = new DispatcherTimer
            {
                Interval = new TimeSpan(0, 0, 0, 3, 0)
            };
            cpuTimer.Tick += DispatcherTimer_Tick;
            cpuTimer.Start();
            #endregion
        }

        private int StatusChange(int value)
        {
            int outVal = 0;
            //状态变化
            if (value == 0)
            {
                outVal = 1;
            }
            else if (value == 1)
            {
                outVal = 2;
            }
            else
            {
                outVal = 0;
            }
            return outVal;
        }
    }
}

3、StatusToColorConverter.cs 转换器代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;

namespace Wpf_Examples.Converters
{
    public class StatusToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is int statusValue)
            {
                switch (statusValue)
                {
                    case 0:
                        return Brushes.Red;
                    case 1:
                        return "#E5D21C";
                    case 2:
                        return Brushes.Green;
                    default:
                        return Brushes.Green; // 默认颜色
                }
            }
            return Brushes.Gray;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

4、动态数字卡实现

1、DataCardWindow.xaml 界面代码实现
<Window x:Class="Wpf_Examples.Views.DataCardWindow"
        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"
        xmlns:local="clr-namespace:Wpf_Examples.Views"
        DataContext="{Binding Source={StaticResource Locator},Path=DataCard}"
        mc:Ignorable="d"
        Title="DataCardWindow" Height="450" Width="800" Background="#2B2B2B">
    <Grid>
        <!--第二列-->
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
            <StackPanel.Resources>
                <DataTemplate x:Key="machineCount">
                    <Border Width="15" Background="#99D40B0B" Margin="2,0">
                        <TextBlock Text="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="16"></TextBlock>
                    </Border>
                </DataTemplate>
            </StackPanel.Resources>
            <TextBlock Text="机台&#13;总数" Foreground="#99ffffff" Margin="10,0" VerticalAlignment="Center" FontSize="10"></TextBlock>
            <ItemsControl ItemsSource="{Binding MachineCount}" ItemTemplate="{StaticResource machineCount}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"></StackPanel>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>

            <TextBlock Text="生产计数" Foreground="#99ffffff" VerticalAlignment="Center" FontSize="10" Margin="20,0"></TextBlock>
            <ItemsControl ItemsSource="{Binding ProductCount}" ItemTemplate="{StaticResource machineCount}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"></StackPanel>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>

            <TextBlock Text="不良计数" Foreground="#99ffffff" Margin="20,0" VerticalAlignment="Center" FontSize="10"></TextBlock>
            <ItemsControl ItemsSource="{Binding BadCount}" ItemTemplate="{StaticResource machineCount}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"></StackPanel>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </StackPanel>
    </Grid>
</Window>

2、DataCardViewModel.cs 代码实现
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging.Messages;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace Wpf_Examples.ViewModels
{
    public class DataCardViewModel:ObservableObject
    {
        #region 计数
        /// <summary>
        /// 机台总数
        /// </summary>
        private string _MachineCount = "02981";

        /// <summary>
        /// 机台总数
        /// </summary>
        public string MachineCount
        {
            get { return _MachineCount; }
            set
            {
               SetProperty(ref _MachineCount, value);
            }
        }

        /// <summary>
        /// 生产计数
        /// </summary>
        private string _ProductCount = "16403";

        /// <summary>
        /// 生产计数
        /// </summary>
        public string ProductCount
        {
            get { return _ProductCount; }
            set
            {
              SetProperty(ref _ProductCount, value);
            }
        }

        /// <summary>
        /// 不良计数
        /// </summary>
        private string _BadCount = "0403";

        /// <summary>
        /// 不良计数
        /// </summary>
        public string BadCount
        {
            get { return _BadCount; }
            set
            {
                SetProperty(ref _BadCount, value);
            }
        }
        #endregion

        public DataCardViewModel()
        {
            CreateTimer();
        }
        private void CreateTimer()
        {
            #region 每秒定时器服务
            DispatcherTimer cpuTimer = new DispatcherTimer
            {
                Interval = new TimeSpan(0, 0, 0, 2, 0)
            };
            cpuTimer.Tick += DispatcherTimer_Tick;
            cpuTimer.Start();
            #endregion
        }

        private void DispatcherTimer_Tick(object sender, EventArgs e)
        {

            ValueChanged();
        }

        private void ValueChanged()
        {
            Random random = new Random();
            ProductCount= random.Next(100, 9999).ToString();
            BadCount = random.Next(100, 999).ToString();
        }
    }
}

3、效果展示

在这里插入图片描述

4.源代码

CSDN下载链接:WPF+MVVM案例实战(三)- 动态数字卡片效果实现


http://www.kler.cn/news/366711.html

相关文章:

  • Linux -- 共享内存(2)
  • C++研发笔记8——C语言程序设计初阶学习笔记6
  • MongoDB简单学习
  • 零基础Java第十期:类和对象(一)
  • 利用客户端导入有关联的业务数据(DBeaver+sql)
  • Vue 项目中 Webpack 常见问题详解
  • 已解决 django.db.utils.OperationalError: (1051, “Unknown table
  • Vue3 学习笔记(七)Vue3 语法-计算属性 computed详解
  • 基于SpringBoot的宠物爱好者交流系统的设计与实现(源码+定制+开发)
  • 厉兵秣马之Java 语言基础和进阶(二)
  • leetcode动态规划(十七)-组合总和IV
  • Python小游戏9——天天酷跑
  • Laravel使用 Swagger
  • 超详细Redis安装配置【包成功的】
  • 系统架构设计师 软件架构的定义与生命周期
  • week08 zookeeper多种安装与pandas数据变换操作-new
  • UE5学习笔记26-添加游戏热身时间,比赛时间,重新开始比赛
  • 【jvm】所有的线程都共享堆吗
  • 【mysql进阶】4-7. 通用表空间
  • 理解 python 类
  • 某ai gpt的bug
  • go的web服务器框架
  • 南京林业大学生态学博士在1区top期刊揭示人工林发育促进土壤团聚体的形成与稳定:对土壤碳氮固存的启示
  • 多端项目开发全流程详解 - 从需求分析到多端部署
  • C语言 | Leetcode C语言题解之第508题斐波那契数
  • 24. Lammps命令学习-系统定义部分总结