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();
}
}
}
效果图: