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;}}}
}
<UserControlx: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;}
}
<UserControlx: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><Borderx: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>
效果图: