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;
}
}
}
您很可能有两个虚拟机实例订阅以接收消息。
不过,这很容易验证。在VM构造函数中生成一个唯一的变量(例如GUID),在接收消息的方法中检查该变量的值。如果它们不匹配,则有两个实例接收消息,并且需要弄清楚代码中发生这种情况的原因。
此外,有时当视图关闭时,虚拟机仍在内存中,而它正在等待垃圾收集,并继续接收消息,因此请确保在视图关闭时取消订阅在虚拟机中接收消息。。。