用wpf替代winform 解决PLC数据量过大页面卡顿的问题

winform 由于不是数据驱动, 页面想刷新数据必须刷新控件, wpf则不用. 可以利用wpf 的数据绑定和IOC, 页面中的消息传递, itemscontrol 实现大量数据刷新, 上位机页面不卡顿

代码如下:

xml 复制代码
<Window
    x:Class="NavTest.Views.NewMainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:con="clr-namespace:ValueConverters;assembly=ValueConverters"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:hc="https://handyorg.github.io/handycontrol"
    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
    xmlns:local="clr-namespace:NavTest.Views"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:mv="clr-namespace:NavTest.ViewModels"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:tt="clr-namespace:NavTest.Eneities"
    xmlns:vc="clr-namespace:NavTest.Components"
    Title="NewMainView"
    Width="1280"
    Height="800"
    d:DataContext="{d:DesignInstance mv:NewMainViewModel}"
    AllowsTransparency="True"
    Background="#2B2C31"
    FontFamily="Microsoft YaHei"
    FontSize="30"
    FontWeight="ExtraLight"
    ResizeMode="CanResizeWithGrip"
    WindowStartupLocation="CenterScreen"
    WindowStyle="None"
    mc:Ignorable="d">
    <Window.Resources>
        <Style x:Key="ControlButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Focusable" Value="False" />
            <Setter Property="Background" Value="#66FFFFFF" />
            <Setter Property="Foreground" Value="White" />
            <Setter Property="FontSize" Value="16" />
            <Setter Property="Width" Value="50" />
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
            <Setter Property="FontFamily" Value="{StaticResource iconfont}" />
            <Setter Property="IsTabStop" Value="False" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid x:Name="LayoutRoot" Background="Transparent">
                            <Rectangle
                                x:Name="ButtonBackground"
                                Fill="{TemplateBinding Background}"
                                Opacity="0" />
                            <Border x:Name="ButtonBorder" SnapsToDevicePixels="true">
                                <ContentPresenter
                                    x:Name="TitleBarButtonContentPresenter"
                                    Margin="{TemplateBinding Padding}"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                    Focusable="False"
                                    RecognizesAccessKey="True"
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                            </Border>
                        </Grid>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter TargetName="ButtonBackground" Property="Opacity" Value="1" />
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="ButtonBackground" Property="Opacity" Value="0.6" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="5*" />
            <ColumnDefinition Width="2*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.3*" />
            <RowDefinition Height="5*" />
        </Grid.RowDefinitions>
        <!--  窗口控制按钮  -->
        <StackPanel
            Grid.Column="3"
            Height="33"
            Margin="0,0,5,0"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Orientation="Horizontal">
            <Button
                Background="#22FFFFFF"
                Content="&#xe7e6;"
                Style="{StaticResource ControlButtonStyle}"
                ToolTip="Minimize">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <i:ChangePropertyAction
                            PropertyName="WindowState"
                            TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
                            Value="Minimized" />
                    </i:EventTrigger>
                    <!--<i:EventTrigger EventName="Click">
                        <i:ChangePropertyAction
                            PropertyName="WindowState"
                            TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
                            Value="Minimized" />
                    </i:EventTrigger>-->
                </i:Interaction.Triggers>
            </Button>
            <Button
                Background="#22FFFFFF"
                Command="{Binding MaxNormorCommand}"
                CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
                Content="&#xe694;"
                FontSize="14"
                Style="{StaticResource ControlButtonStyle}"
                ToolTip="Maximize" />
            <Button
                Background="Red"
                Content="&#xe653;"
                Style="{StaticResource ControlButtonStyle}"
                ToolTip="Close">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <i:CallMethodAction MethodName="Close" TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
        </StackPanel>
        <Border
            Grid.Row="2"
            Grid.RowSpan="2"
            Margin="5,5,5,58"
            Padding="10"
            Background="White"
            BorderBrush="Gray"
            BorderThickness="1"
            CornerRadius="5">
            <Border.Effect>
                <DropShadowEffect />
            </Border.Effect>
            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Top">
                <TextBlock
                    Margin="5,25,5,5"
                    HorizontalAlignment="Center"
                    Text="Main">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseUp">
                            <i:InvokeCommandAction Command="{Binding SwitchPageCommand}" CommandParameter="main" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </TextBlock>
                <TextBlock
                    Margin="5,25,5,5"
                    HorizontalAlignment="Center"
                    Text="Page1">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseUp">
                            <i:InvokeCommandAction Command="{Binding SwitchPageCommand}" CommandParameter="page1" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </TextBlock>
                <TextBlock
                    Margin="5,25,5,5"
                    HorizontalAlignment="Center"
                    Text="Page2">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseUp">
                            <i:InvokeCommandAction Command="{Binding SwitchPageCommand}" CommandParameter="page2" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </TextBlock>
                <TextBlock
                    Margin="5,25,5,5"
                    HorizontalAlignment="Center"
                    Text="Page3">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseUp">
                            <i:InvokeCommandAction Command="{Binding SwitchPageCommand}" CommandParameter="page3" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </TextBlock>
                <TextBlock
                    Margin="5,25,5,5"
                    HorizontalAlignment="Center"
                    Text="Page5">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseUp">
                            <i:InvokeCommandAction Command="{Binding SwitchPageCommand}" CommandParameter="page5" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </TextBlock>
            </StackPanel>
        </Border>
        <ContentControl
            x:Name="container"
            Grid.Row="2"
            Grid.RowSpan="2"
            Grid.Column="1"
            Grid.ColumnSpan="2"
            Margin="5,5,5,5"
            Content="{Binding MyContent}" />
    </Grid>
</Window>
xml 复制代码
<UserControl
    x:Class="NavTest.Views.Page2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:con="clr-namespace:ValueConverters;assembly=ValueConverters"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:hc="https://handyorg.github.io/handycontrol"
    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
    xmlns:local="clr-namespace:NavTest.Views"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:mv="clr-namespace:NavTest.ViewModels"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:tt="clr-namespace:NavTest.Eneities"
    xmlns:vc="clr-namespace:NavTest.Components"
    d:DataContext="{d:DesignInstance mv:Page2ViewModel}"
    d:DesignHeight="450"
    d:DesignWidth="800"
    FontSize="22"
    mc:Ignorable="d">

    <Grid>
        <ItemsControl AlternationCount="2" ItemsSource="{Binding PLCModels}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border x:Name="border" Padding="2">
                        <StackPanel>
                            <TextBlock Foreground="White" Text="{Binding Id}" />
                            <TextBlock Foreground="White" Text="{Binding Name}" />
                            <TextBlock Foreground="White" Text="{Binding PlcValue}" />
                        </StackPanel>
                    </Border>
                    <DataTemplate.Triggers>
                        <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                            <Setter TargetName="border" Property="Background" Value="red" />
                        </Trigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>

</UserControl>
csharp 复制代码
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using NavTest.Eneities;
using NavTest.Views;
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;

namespace NavTest.ViewModels
{
    public partial class NewMainViewModel : ObservableRecipient
    {

        public NewMainViewModel(Page1 page1, Page2 page2, Page3 page3, Page5 page5, ObservableCollection<PLCModel> pLCModels)
        {
            this.page1 = page1;
            this.page2 = page2;
            this.page3 = page3;
            this.page5 = page5;
            this.pLCModels = pLCModels;

            IsActive = true;
            this.MyContent = page2;
            PlcGetValue();
        }

        [ObservableProperty]
        private object? myContent;
        private readonly Page1 page1;
        private readonly Page2 page2;
        private readonly Page3 page3;
        private readonly Page5 page5;
        [ObservableProperty]
        private ObservableCollection<PLCModel> pLCModels;


        private int myUshort1;

        public int MyUshort1
        {
            get => myUshort1;
            set => SetProperty(ref myUshort1, value, true);
        }

        [RelayCommand]
        public void MaxNormor(Window window)
        {
            window.WindowState =
                window.WindowState == WindowState.Maximized
                    ? WindowState.Normal
                    : WindowState.Maximized;
        }

        [RelayCommand]
        public void SwitchPage(string str)
        {

            switch (str)
            {
                case "main":
                    //this.MyContent;
                    break;
                case "page1":
                    this.MyContent = page1;
                    break;
                case "page2":
                    this.MyContent = page2;
                    break;
                case "page3":
                    this.MyContent = page3;
                    break;
                case "page5":
                    this.MyContent = page5;
                    break;
                default:
                    break;
            }
        }


        private void PlcGetValue()
        {
            Task.Run(async () =>
            {

                while (true)
                {
                    await Task.Delay(500);
                    PLCModels = new();
                    for (int i = 0; i < 90; i++)
                    {
                        var random = new Random();
                        PLCModels.Add(new()
                        {
                            Id = i,
                            Name = $"Name{i}",
                            PlcValue = random.Next(1, 500)
                        });
                        if (i == 10)
                        {
                            MyUshort1 = random.Next(1, 500);
                        }
                    }
                }
            });
        }
    }
}
csharp 复制代码
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
using NavTest.Eneities;
using System.Collections.ObjectModel;

namespace NavTest.ViewModels
{
    public partial class Page2ViewModel : ObservableRecipient, IRecipient<PropertyChangedMessage<int>>
    {
        [ObservableProperty]
        private ObservableCollection<PLCModel> pLCModels;

        public Page2ViewModel(ObservableCollection<PLCModel> pLCModels)
        {

            this.PLCModels = pLCModels;
            IsActive = true;

        }

        public void Receive(PropertyChangedMessage<int> message)
        {
            if (message.Sender is NewMainViewModel vm)
            {
                this.PLCModels = vm.PLCModels;
            }
        }
    }
}
csharp 复制代码
using Microsoft.Extensions.DependencyInjection;
using NavTest.Eneities;
using NavTest.Views;
using System;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Windows;

namespace NavTest
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public App() => Services = ConfigureServices();

        public IServiceProvider? Services { get; }

        public new static App Current => (App)Application.Current;

        private IServiceProvider? ConfigureServices()
        {
            ServiceCollection services = new ServiceCollection();

            //View
            #region ViewModel,View 注入

            services.AddSingleton<NewMainView>();
            services.AddSingleton<Page1>();
            services.AddSingleton<Page2>();
            services.AddSingleton<Page3>();
            services.AddSingleton<Page5>();
            var viewModelTypes = Assembly.GetExecutingAssembly().GetTypes()
                .Where(t => t.Name.EndsWith("ViewModel"));

            foreach (var type in viewModelTypes)
            {
                services.AddScoped(type);
            }

            //services.AddSingleton<Page2>(sp => new Page2()
            //{
            //    DataContext = sp.GetService<Page2ViewModel>()
            //});


            #endregion

            //PLC注入
            services.AddSingleton<ObservableCollection<PLCModel>>();

            return services.BuildServiceProvider();
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            NewMainView newMainView = this.Services?.GetService<NewMainView>();
            newMainView.Show();
            //MainView? mainView = this.Services?.GetService<MainView>();
            //mainView.DataContext = this.Services?.GetService<MainViewModel>();
            //mainView.Show();
        }
    }
}

效果图:

相关推荐
❀always❀1 天前
深入浅出分布式限流(更新中)
分布式·wpf
深漂阿碉2 天前
WPF打包exe应用的图标问题
wpf
三千道应用题2 天前
WPF学习笔记(26)CommunityToolkit.Mvvm与MaterialDesignThemes
wpf
SEO-狼术4 天前
DevExpress WPF Crack, DevExpress WPF v25.1
wpf
小老鼠爱大米4 天前
C# WPF - Prism 学习篇:搭建项目(一)
c#·wpf·prism
博睿谷IT99_4 天前
Hadoop 分布式存储与计算框架详解
wpf
qq_392397126 天前
Redis常用操作
数据库·redis·wpf
三千道应用题6 天前
WPF学习笔记(25)MVVM框架与项目实例
wpf
厦门德仔6 天前
【WPF】WPF(样式)
android·java·wpf
三千道应用题6 天前
WPF学习笔记(24)命令与ICommand接口
wpf