winform 由于不是数据驱动, 页面想刷新数据必须刷新控件, wpf则不用. 可以利用wpf 的数据绑定和IOC, 页面中的消息传递, itemscontrol 实现大量数据刷新, 上位机页面不卡顿
跨页面传值, 可以用两种方法: Toolkit.Mvvm中的Message和IOC. 下面是代码:
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<PLCModels>();
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();
}
}
}
模型定义:
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel;
namespace NavTest.Eneities
{
public partial class PLCModel : INotifyPropertyChanged
{
public int Id { get; set; }
public string? Name { get; set; }
public string? DataType { get; set; }
//[ObservableProperty]
//private int plcValue;
private int plcValue;
public event PropertyChangedEventHandler? PropertyChanged;
public int PlcValue
{
get => plcValue;
set
{
if (plcValue != value)
{
plcValue = value;
NotifyPropertyChanged(nameof(PlcValue));
}
}
}
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NavTest.Eneities
{
public partial class PLCModels
{
public PLCModels()
{
for (int i = 0; i < 200; i++)
{
pLCModels.Add(new PLCModel()
{
Id = i,
PlcValue = i,
Name = $"名字{i}",
});
}
}
public ObservableCollection<PLCModel> pLCModels { get; set; } = new();
}
}
主页面产生数据:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using NavTest.Eneities;
using NavTest.Views;
using NPOI.SS.Formula.Functions;
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, PLCModels pLCModelsIoc)
{
this.page1 = page1;
this.page2 = page2;
this.page3 = page3;
this.page5 = page5;
this.pLCModelsIoc = pLCModelsIoc;
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;
private PLCModels pLCModelsIoc;
[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);
//用Message传递
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);
}
}
//用Ioc传递
for (int j = 0; j < 200; j++)
{
var random = new Random();
pLCModelsIoc.pLCModels[j].PlcValue = random.Next(1, 500);
}
}
});
}
}
}
用ViewModel的Message 传值:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
using NavTest.Eneities;
using System.Collections.ObjectModel;
namespace NavTest.ViewModels
{
/// <summary>
/// 用ViewModel 的 Message传递变化的值
/// </summary>
public partial class Page2ViewModel : ObservableRecipient, IRecipient<PropertyChangedMessage<int>>
{
[ObservableProperty]
private ObservableCollection<PLCModel> pLCModels;
public Page2ViewModel()
{
IsActive = true;
}
public void Receive(PropertyChangedMessage<int> message)
{
if (message.Sender is NewMainViewModel vm)
{
this.PLCModels = vm.PLCModels;
}
}
}
}
<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>
<Grid.RowDefinitions>
<RowDefinition Height="0.1*" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Foreground="White" Text="用viewModel的消息传递" />
</StackPanel>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ItemsControl AlternationCount="2" ItemsSource="{Binding PLCModels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border x:Name="border" Padding="2" BorderThickness="2" BorderBrush="Cyan">
<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="green" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
用IOC传值:
using CommunityToolkit.Mvvm.ComponentModel;
using NavTest.Eneities;
using System.Collections.ObjectModel;
namespace NavTest.ViewModels
{
/// <summary>
/// 用Ioc传递变化的值
/// </summary>
public partial class Page3ViewModel : ObservableObject
{
public Page3ViewModel(PLCModels pLCModelsIoc)
{
pLCModels = pLCModelsIoc.pLCModels;
}
[ObservableProperty]
private ObservableCollection<PLCModel> pLCModels;
}
}
<UserControl
x:Class="NavTest.Views.Page3"
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: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:Page3ViewModel}"
d:DesignHeight="450"
d:DesignWidth="800"
FontSize="24"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.1*" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Foreground="White" Text="用Ioc传递" />
</StackPanel>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ItemsControl AlternationCount="2" ItemsSource="{Binding PLCModels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border
x:Name="border"
Padding="2"
BorderBrush="Yellow"
BorderThickness="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="Blue" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
效果图: