WPF MvvmLight Register,Send,Unregister
//Register Messenger.Default.Register<object>(this, "ShowItemsCountToken", ShowItemsCount); //Send Messenger.Default.Send<object>(obj, "ShowItemsCountToken"); //Unregister Messenger.Default.Unregister<object>(this,"CountToken"); //Action<object> action public void ShowItemsCount(object obj) { var lbx = obj as ListBox; if(lbx!=null && lbx.Items!=null) { var items = lbx.Items.Cast<Book>()?.ToList(); if(items!=null &&items.Any()) { MessageBox.Show($"Count:{items.Count}"); } } }
In Nuget search MvvmLight and install
// // Summary: // Registers a recipient for a type of message TMessage. The action parameter will // be executed when a corresponding message is sent. See the receiveDerivedMessagesToo // parameter for details on how messages deriving from TMessage (or, if TMessage // is an interface, messages implementing TMessage) can be received too. // // Registering a recipient does not create a hard reference to it, so if this recipient // is deleted, no memory leak is caused. // // Parameters: // recipient: // The recipient that will receive the messages. // // token: // A token for a messaging channel. If a recipient registers using a token, and // a sender sends a message using the same token, then this message will be delivered // to the recipient. Other recipients who did not use a token when registering (or // who used a different token) will not get the message. Similarly, messages sent // without any token, or with a different token, will not be delivered to that recipient. // // // action: // The action that will be executed when a message of type TMessage is sent. // // keepTargetAlive: // If true, the target of the Action will be kept as a hard reference, which might // cause a memory leak. You should only set this parameter to true if the action // is using closures. See http://galasoft.ch/s/mvvmweakaction. // // Type parameters: // TMessage: // The type of message that the recipient registers for. void Register<TMessage>(object recipient, object token, Action<TMessage> action, bool keepTargetAlive = false); // // Summary: // Sends a message to registered recipients. The message will reach only recipients // that registered for this message type using one of the Register methods, and // that are of the targetType. // // Parameters: // message: // The message to send to registered recipients. // // token: // A token for a messaging channel. If a recipient registers using a token, and // a sender sends a message using the same token, then this message will be delivered // to the recipient. Other recipients who did not use a token when registering (or // who used a different token) will not get the message. Similarly, messages sent // without any token, or with a different token, will not be delivered to that recipient. // // // Type parameters: // TMessage: // The type of message that will be sent. void Send<TMessage>(TMessage message, object token); // // Summary: // Unregisters a message recipient for a given type of messages only and for a given // token. After this method is executed, the recipient will not receive messages // of type TMessage anymore with the given token, but will still receive other message // types or messages with other tokens (if it registered for them previously). // // Parameters: // recipient: // The recipient that must be unregistered. // // token: // The token for which the recipient must be unregistered. // // Type parameters: // TMessage: // The type of messages that the recipient wants to unregister from. void Unregister<TMessage>(object recipient, object token);
Full code
<Window x:Class="WpfApp379.MainWindow" 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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp379" mc:Ignorable="d" WindowState="Maximized" Title="MainWindow" Height="450" Width="800"> <Window.DataContext> <local:BookVM/> </Window.DataContext> <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition/> </Grid.RowDefinitions> <ToolBar Grid.Row="0"> <Button Content="Load" Command="{Binding LoadCmd}" Width="100"/> </ToolBar> <ListBox x:Name="lbx" Grid.Row="1" BorderBrush="Blue" BorderThickness="5" VirtualizingPanel.CacheLength="100" VirtualizingPanel.CacheLengthUnit="Item" VirtualizingPanel.IsContainerVirtualizable="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ItemsSource="{Binding BooksCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> <ListBox.ContextMenu> <ContextMenu> <MenuItem Header="Export NewtonSoftJson" FontSize="50" Foreground="Red" Command="{Binding ExportNewtonJsonCmd}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContextMenu}},Path=PlacementTarget}"/> <MenuItem Header="Export BinaryFormatter" FontSize="50" Foreground="Red" Command="{Binding ExportBinaryFormatterCmd}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ContextMenu}},Path=PlacementTarget}"/> <MenuItem Header="Show ItemsCount" FontSize="50" Foreground="Red" Command="{Binding ShowItemcCountCmd}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ContextMenu}},Path=PlacementTarget}"/> </ContextMenu> </ListBox.ContextMenu> <ListBox.ItemTemplate> <DataTemplate> <Grid> <Image Source="{Binding ImgUrl}" Width="{Binding ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}" Height="{Binding ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/> <TextBlock Text="{Binding Name}" FontSize="150" Foreground="Red" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Window> //cs using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.IO; using Microsoft.Win32; using Newtonsoft.Json; using System.Runtime.Serialization.Formatters.Binary; using GalaSoft.MvvmLight.Messaging; namespace WpfApp379 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public class BookVM : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) { handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } private ObservableCollection<Book> booksCollection; public ObservableCollection<Book> BooksCollection { get { return booksCollection; } set { if (value != booksCollection) { booksCollection = value; OnPropertyChanged(nameof(BooksCollection)); } } } public BookVM() { InitCmds(); InitData(); } ~BookVM() { Messenger.Default.Unregister<object>(this,"CountToken"); } public DelCmd LoadCmd { get; set; } public DelCmd ExportNewtonJsonCmd { get; set; } public DelCmd ExportBinaryFormatterCmd { get; set; } public DelCmd ShowItemcCountCmd { get; set; } private void InitCmds() { LoadCmd = new DelCmd(LoadCmdExecuted); ExportNewtonJsonCmd = new DelCmd(ExportNewtonJsonCmdExecuted); ExportBinaryFormatterCmd = new DelCmd(ExportBinaryFormatterCmdExecuted); ShowItemcCountCmd = new DelCmd(ShowItemcCountCmdExecuted); RegisterCommands(); } private void ShowItemcCountCmdExecuted(object obj) { Messenger.Default.Send<object>(obj, "ShowItemsCountToken"); } private void RegisterCommands() { Messenger.Default.Register<object>(this, "ShowItemsCountToken", ShowItemsCount); } public void ShowItemsCount(object obj) { var lbx = obj as ListBox; if(lbx!=null && lbx.Items!=null) { var items = lbx.Items.Cast<Book>()?.ToList(); if(items!=null &&items.Any()) { MessageBox.Show($"Count:{items.Count}"); } } } private void ExportBinaryFormatterCmdExecuted(object obj) { var lbx = obj as ListBox; if (lbx != null) { var items = lbx.Items.Cast<Book>()?.ToList(); if (items != null && items.Any()) { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "All Files|*.*|Json Files|*.json"; dialog.FileName = $"Bin{DateTime.Now.ToString("yyyyMMddHHmmssffff")}_{Guid.NewGuid().ToString("N")}.bin"; if (dialog.ShowDialog() == true) { using (FileStream fs = new FileStream(dialog.FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { BinaryFormatter binFormatter = new BinaryFormatter(); binFormatter.Serialize(fs, items); } MessageBox.Show($"Binary Serialized in {dialog.FileName}", "Binary Serialize", MessageBoxButton.OK); } } } } private void ExportNewtonJsonCmdExecuted(object obj) { var lbx = obj as ListBox; if(lbx!=null) { var items = lbx.Items.Cast<Book>()?.ToList(); if(items!=null && items.Any()) { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "All Files|*.*|Json Files|*.json"; dialog.FileName = $"Json{DateTime.Now.ToString("yyyyMMddHHmmssffff")}_{Guid.NewGuid().ToString("N")}.json"; if(dialog.ShowDialog()==true) { string jsonStr=JsonConvert.SerializeObject(items,Formatting.Indented); File.AppendAllText(dialog.FileName, jsonStr); MessageBox.Show($"Saved in {dialog.FileName}", "Saved Json", MessageBoxButton.OK); } } } } private void LoadCmdExecuted(object obj) { InitData(); } private void InitData() { var imgsList = Directory.GetFiles("../../Images"); if (imgsList != null && imgsList.Count() > 0) { int imgsCount = imgsList.Count(); BooksCollection = new ObservableCollection<Book>(); for (int i = 0; i < 1000000; i++) { BooksCollection.Add(new Book() { Id = i + 1, Name = $"Name_{i + 1}", Title = $"Title_{i + 1}", Topic = $"Topic_{i + 1}", ImgUrl = imgsList[i % imgsCount] }); } } } } public class DelCmd : ICommand { public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } private Action<object> execute; private Predicate<object> canExecute; public DelCmd(Action<object> executeValue, Predicate<object> canExecuteValue) { execute = executeValue; canExecute = canExecuteValue; } public DelCmd(Action<object> executeValue) : this(executeValue, null) { } public bool CanExecute(object parameter) { if (canExecute == null) { return true; } return canExecute(parameter); } public void Execute(object parameter) { execute(parameter); } } [Serializable] public class Book { public int Id { get; set; } public string ImgUrl { get; set; } public string Name { get; set; } public string Title { get; set; } public string Topic { get; set; } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2019-09-18 wpf button style IsMouseOver