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

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

代码如下:

<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}">
            "Focusable" Value="False" />
            "Background" Value="#66FFFFFF" />
            "Foreground" Value="White" />
            "FontSize" Value="16" />
            "Width" Value="50" />
            "HorizontalContentAlignment" Value="Center" />
            "VerticalContentAlignment" Value="Center" />
            "WindowChrome.IsHitTestVisibleInChrome" Value="True" />
            "FontFamily" Value="{StaticResource iconfont}" />
            "IsTabStop" Value="False" />
            "Template">
                
                    "{x:Type Button}">
                        x:Name="LayoutRoot" Background="Transparent">
                            x:Name="ButtonBackground"
                                Fill="{TemplateBinding Background}"
                                Opacity="0" />
                            x:Name="ButtonBorder" SnapsToDevicePixels="true">
                                x:Name="TitleBarButtonContentPresenter"
                                    Margin="{TemplateBinding Padding}"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                    Focusable="False"
                                    RecognizesAccessKey="True"
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                            
                        

                        
                            "IsMouseOver" Value="true">
                                "ButtonBackground" Property="Opacity" Value="1" />
                            
                            "IsPressed" Value="True">
                                "ButtonBackground" Property="Opacity" Value="0.6" />
                            
                        
                    
                
            
        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=""
                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:Interaction.Triggers>
            Button>
            <Button
                Background="#22FFFFFF"
                Command="{Binding MaxNormorCommand}"
                CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
                Content=""
                FontSize="14"
                Style="{StaticResource ControlButtonStyle}"
                ToolTip="Maximize" />
            <Button
                Background="Red"
                Content=""
                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>

<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>




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);
                        }
                    }
                }
            });
        }
    }
}

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;
            }
        }
    }
}

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
{
    /// 
    /// Interaction logic for App.xaml
    /// 
    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(sp => new Page2()
            //{
            //    DataContext = sp.GetService()
            //});


            #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.DataContext = this.Services?.GetService();
            //mainView.Show();
        }
    }
}

效果图:

用wpf替代winform 解决PLC数据量过大页面卡顿的问题_第1张图片

你可能感兴趣的:(wpf)