2014-10-06 102 views
0

我正在嘗試使用Galasoft Messaging,並且似乎在接收消息的用戶控件中遇到了一個有趣的行爲。消息傳遞似乎很好,但在用戶控件視圖模型中收到消息時調用的方法似乎執行了兩次。使用控制檯輸出(Console.WriteLine)進行驗證時,它顯示消息僅由主窗口發送一次。在用戶控制端,控制檯輸出總是顯示消息兩次...是否有可能有2個實例化的視圖模型實例? 主窗口中,該廣播消息如下所示:GalaSoft.MvvmLight.Messaging - 重複消息

代碼背後:

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; 
     } 
    } 
} 

回答

2

這很可能是您訂閱了VM的兩個實例接收消息。

雖然這很容易驗證。在VM構造函數中生成一個唯一變量(例如GUID),並在接收消息的方法中檢查該變量的值。如果它們不匹配,則有兩個實例接收到該消息,並需要弄清楚爲什麼會發生在您的代碼中。

此外,有時虛擬機在視圖關閉時仍保留在內存中,等待垃圾收集,並繼續接收消息,因此請確保在視圖關閉時取消訂閱接收虛擬機中的消息。 。