GalaSoft.MvvvmLight.Messaging-重复消息

本文关键字:消息 Messaging- MvvvmLight GalaSoft | 更新日期: 2023-09-27 18:25:52

我正在尝试使用Galasoft Messaging,在接收消息的用户控件中似乎遇到了一个有趣的行为。消息传递似乎进行得很好,但在用户控件视图模型中接收到消息时调用的方法似乎执行了两次。使用控制台输出(console.WriteLine)进行验证,主窗口似乎只发送了一次消息。在用户控制端,控制台输出似乎总是显示两次消息。。。是否有可能存在正在实例化的视图模型的2个实例?广播消息的主窗口如下:

代码背后:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
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 ETGTools;
using System.Security.Principal;
using ETG.Interfaces;
using GalaSoft.MvvmLight.Messaging;
using ETGTools.Views;
using Telerik.Windows.Controls;
namespace MessengerDemo.Views
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public string gcETGVersion = "v123";
        public int iii = 0;
        public MainWindow()
        {
            InitializeComponent();
            LoadTabs();
            winCon.Title = winCon.Title + " (assembly666)";
            tbxUser.Text = "schin";
        }
        private void LoadTabs()
        {
            var dllsPath = new List<string> {
                @"C:'workspaceVS'ETGTools'trunk'Tools'bin'Debug'ETGTools.dll"
            };
            foreach (var dllPath in dllsPath)
            {
                var assembly = Assembly.LoadFrom(dllPath);
                var typeName = (from type in assembly.GetTypes()
                                where type.GetInterface("ETG.Interfaces.ITab") != null
                                select type.FullName).SingleOrDefault();
                var uc = assembly.CreateInstance(typeName, true);
                var tab = (ITab)uc;
                tab.Init();
                RadTabItem rTi = new RadTabItem();
                rTi.Header = tab.description;
                Grid gRd = new Grid();
                gRd.Children.Add((UserControl)uc);
                rTi.Content = gRd;
                tabControl.Items.Add(rTi);
            }
        }
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            Messenger.Default.Send<string>(tbxOrd.Text, "String_ToHelpMatchTheMsg");
            iii++;
            Console.WriteLine("mainwindow loop count: " + iii);
        }
    }
}

主XAML:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:UC="clr-namespace:ETGTools;assembly=ETGTools"
        xmlns:UCV="clr-namespace:ETGTools.Views;assembly=ETGTools"
        xmlns:UCVM="clr-namespace:ETGTools.ViewModels;assembly=ETGTools"
        xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" x:Class="MessengerDemo.Views.MainWindow"
        xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
        x:Name="winCon" Title="MessengerDemo" Height="800" Width="1100" Background="LightBlue" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Closing">
            <command:EventToCommand Command="{Binding CloseCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Window.Resources>
        <Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
            <Setter Property="Visibility" Value="Collapsed" />
        </Style>
        <Style x:Key="listViewItemStyle" TargetType="{x:Type ListViewItem}">
        </Style>
            <Style x:Key="steviesRadListBoxItemStyle" TargetType="telerik:RadListBoxItem">
                <Setter Property="Padding" Value="3" />
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="VerticalContentAlignment" Value="Top" />
                <Setter Property="Background" Value="Transparent" />
                <Setter Property="BorderBrush" Value="Transparent" />
                <Setter Property="BorderThickness" Value="1" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="telerik:RadListBoxItem">
                            <Grid>
                                <Border >
                                    <Border BorderThickness="1" BorderBrush="Black" Background="{Binding oops}"/>
                                </Border>
                                <ContentPresenter x:Name="contentPresenter" Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    </Window.Resources>
    <Border Margin="93,39,16,37" BorderBrush="SlateBlue" BorderThickness="2">
    <Grid Name="grdApps" ShowGridLines="True">
            <telerik:Label Content="Productivity Gauge" HorizontalAlignment="Left" Margin="272,-33,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.444,-0.158" Width="112" FontStyle="Italic"/>
            <telerik:Label x:Name="lblTrend" Content="trending" HorizontalAlignment="Left" Margin="468,-33,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.444,-0.158" Width="66" FontStyle="Italic" ToolTip="tap to refresh!">
                <telerik:EventToCommandBehavior.EventBindings>
                    <telerik:EventBinding Command="{Binding CountCommand}" EventName="MouseLeftButtonDown"
RaiseOnHandledEvents="True" PassEventArgsToCommand="True" />
                </telerik:EventToCommandBehavior.EventBindings>
            </telerik:Label>
            <TextBox x:Name="tbxOrds" Background="{Binding Xaml1.Color1}" HorizontalAlignment="Left" Height="23" Margin="384,-37,0,0" TextWrapping="Wrap" Text="{Binding Xaml1.Text1, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="77" Padding="0" VerticalContentAlignment="Bottom" IsEnabled="True" HorizontalContentAlignment="Center" FontWeight="SemiBold" ToolTip="" IsReadOnly="True"/>
            <Label Content="Buyer/Owner" HorizontalAlignment="Left" Margin="38,10,0,0" VerticalAlignment="Top"/>
            <TextBox Name="tbxBName" Text="{Binding Order1.BName}" HorizontalAlignment="Left" Height="23" Margin="130,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="264" RenderTransformOrigin="0.476,-0.135" IsEnabled="False"/>
            <Label Content="Seller" HorizontalAlignment="Left" Margin="38,30,0,0" VerticalAlignment="Top"/>
            <TextBox Name="tbxSName" Text="{Binding Order1.SName}" HorizontalAlignment="Left" Height="23" Margin="130,32,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="264" RenderTransformOrigin="0.476,-0.135" IsEnabled="False"/>
            <Label Content="Address" HorizontalAlignment="Left" Margin="38,50,0,0" VerticalAlignment="Top"/>
            <TextBox Name="tbxAddr" Text="{Binding Order1.Addr}" HorizontalAlignment="Left" Height="23" Margin="130,52,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="264" RenderTransformOrigin="0.476,-0.135" IsEnabled="False"/>
            <Label Content="Order #" HorizontalAlignment="Left" Margin="735,29,0,0" VerticalAlignment="Top"/>
            <TextBox x:Name="tbxUser" Text="{Binding Order1.FUser, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" HorizontalAlignment="Left" Height="23" Margin="399,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="164" RenderTransformOrigin="0.476,-0.135" IsEnabled="False"/>
            <TextBox Visibility="{Binding Xaml1.Visibility1, UpdateSourceTrigger=PropertyChanged}" Name="tbxOrd" Text="{Binding Order1.Escrow, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Height="23" Margin="789,30,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.476,-0.135"/>
            <TextBox Name="test" Text="{Binding Order1.Status, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Height="23" Margin="789,7,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.476,-0.135" IsEnabled="False"/>
            <Button Content="GO" HorizontalAlignment="Left" Margin="924,32,0,0" VerticalAlignment="Top" Width="28" Click="Button_Click_1"/>
            <Button  Content="Help!" HorizontalAlignment="Left" Margin="924,57,0,0" VerticalAlignment="Top" Width="28" RenderTransformOrigin="0.5,1.75"/>
            <Grid HorizontalAlignment="Left" Height="601" Margin="21,75,0,0" VerticalAlignment="Top" Width="931">
                    <telerik:RadTabControl Name="tabControl" Margin="10">
                    <telerik:RadTabItem Header="Delivery" Height="30" Width="60" Visibility="{Binding Xaml1.Visibility1, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
                        <Grid HorizontalAlignment="Left" Height="601" VerticalAlignment="Top" Width="931" Visibility="{Binding Xaml1.Visibility1, UpdateSourceTrigger=PropertyChanged}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <UCV:DeliveryUC UCESI="{Binding Path=ESIs, Mode=TwoWay}"  UC1="{Binding DataContext.ContainerData, ElementName=winCon, Mode=TwoWay}" />
                        </Grid>
                    </telerik:RadTabItem>
                </telerik:RadTabControl>
        </Grid>
            <Border HorizontalAlignment="Left" Height="680" VerticalAlignment="Top" Width="83" BorderBrush="Blue" BorderThickness="2" Margin="-87,-4,0,0">
                <Grid Name="grdL20" Margin="-83,-2,83,2" >
                    <Grid.RowDefinitions>
                        <RowDefinition Height="600*"/>
                        <RowDefinition Height="69*"/>
                    </Grid.RowDefinitions>
                    <Image HorizontalAlignment="Left" Height="100" Margin="83,1,-83,0" VerticalAlignment="Top" Width="79" Source="/MessengerDemo;component/images/charlieC.png"/>
                    <Label BorderThickness="2" BorderBrush="Blue" Content="Last 20 Files" HorizontalAlignment="Left" Margin="83,105,-83,0" VerticalAlignment="Top" Width="80"/>
                    <telerik:RadListBox x:Name="rlbLast20" ItemsSource="{Binding ULast}" DisplayMemberPath="Last20"
                                        Visibility="{Binding Xaml1.Visibility1, UpdateSourceTrigger=PropertyChanged}"
                                        ItemContainerStyle="{StaticResource steviesRadListBoxItemStyle}"
                                        HorizontalAlignment="Left" Margin="83,135,-83,0" VerticalAlignment="Top" Width="80" Height="400" Background="Salmon" Foreground="{DynamicResource {x:Static SystemColors.ActiveCaptionTextBrushKey}}" ScrollViewer.HorizontalScrollBarVisibility="Hidden" MaxHeight="400">
                        <telerik:RadListBox.BindingGroup>
                            <BindingGroup/>
                        </telerik:RadListBox.BindingGroup>
                        <telerik:EventToCommandBehavior.EventBindings>
                            <telerik:EventBinding Command="{Binding CustomCommand}" EventName="MouseDoubleClick"
RaiseOnHandledEvents="True" PassEventArgsToCommand="True" />
                        </telerik:EventToCommandBehavior.EventBindings>
                    </telerik:RadListBox>
                    <CheckBox Name="cbxCook" Content="cookies" HorizontalAlignment="Left" Margin="97,35,-69,0" VerticalAlignment="Top" IsChecked="{Binding Xaml1.Checked1, UpdateSourceTrigger=PropertyChanged}" Command="{Binding CheckCommand}" Grid.Row="1" />
                </Grid>
            </Border>
        </Grid>
    </Border>
</Window>

为消息注册的用户控件(视图模型):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Windows;
using GalaSoft.MvvmLight.Messaging;
namespace ETGTools.ViewModels
{
    using System.Windows.Input;
    using ETGTools.Views;
    using ETGTools.Models;
    using ETGTools.Commands;
    public class DisclosureControlViewModel : DependencyObject, INotifyPropertyChanged
    {
        private int iii = 0;
        private int jjj = 0;
        private string _viewModelStringProperty;
        public string ViewModelStringProperty
        {
            get { return _viewModelStringProperty; }
            set
            {
                _viewModelStringProperty = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("ViewModelStringProperty"));
                }
            }
        }
        public DisclosureControlViewModel()
        {
            _DiscCntl = new DiscCntl();
            _Xaml1 = new Xaml1();
            Xaml1.Focusable1 = true;
            Xaml1.Enabled1 = false;
            _UserProfile = new UserProfile();
            UserProfile.Pwd = UC1+"please";
            UserProfile.User = "what: " + ViewModelStringProperty;
            GoCommand = new GoCommand(this);
            Messenger.Default.Register<string>(this, "String_ToHelpMatchTheMsg", executeThisFunction);
            jjj++;
        }
        private void executeThisFunction(string strMsg)
        {
            //your code would go here to run upon receiving the message
            // The following line will display: "Dummy text message" 
            //MessageBox.Show("msg passed: " + strMsg);
            iii++;
            Console.WriteLine("in UC jjj:"+jjj.ToString()+", iii:"+iii.ToString()+", msg passed: " + strMsg);
            return;
        }
        private string _uC1;
        public string UC1
        {
            get { return _uC1; }
            set
            {
                _uC1 = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("UC1"));
                }
            }
        }
        private UserProfile _UserProfile;
        public UserProfile UserProfile
        {
            get
            {
                return _UserProfile;
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        private ETGTools.Models.Xaml1 _Xaml1;
        public ETGTools.Models.Xaml1 Xaml1
        {
            get
            {
                return _Xaml1;
            }
        }
        private DiscCntl _DiscCntl;
        public DiscCntl DiscCntl
        {
            get
            {
                return _DiscCntl;
            }
        }
        public void DoGo()
        {
            Xaml1.Focusable1 = false;
            Xaml1.Enabled1 = true;
        }
        public bool CanGo
        {
            get
            {
                if (DiscCntl == null)
                {
                    return false;
                }
                return !String.IsNullOrWhiteSpace(DiscCntl.Id);
            }
        }
        public ICommand GoCommand
        {
            get;
            private set;
        }
    }
}

GalaSoft.MvvvmLight.Messaging-重复消息

您很可能有两个虚拟机实例订阅以接收消息。

不过,这很容易验证。在VM构造函数中生成一个唯一的变量(例如GUID),在接收消息的方法中检查该变量的值。如果它们不匹配,则有两个实例接收消息,并且需要弄清楚代码中发生这种情况的原因。

此外,有时当视图关闭时,虚拟机仍在内存中,而它正在等待垃圾收集,并继续接收消息,因此请确保在视图关闭时取消订阅在虚拟机中接收消息。。。