2016-11-09 54 views
1

我下面的代码在我的WPF App.xaml.cs文件:问题与app.xaml.cs到MainViewmodel通信

void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) 
     { 
      var mainVM = MainWindowViewModel.Instance; 
      mainVM.DisplayMessage = string.Format("Something went wrong and it has been logged...If the problem persists, please contact {0}.", mainVM.NotificationsReceiver); 
      mainVM.DisplayMessageForegroundColor = "Red"; 

     e.Handled = true; 
    } 

MainWindowViewModel.cs

public string DisplayMessage 
     { 
      get 
      { 
       return m_displayMessage; 
      } 
      set 
      { 
       m_displayMessage = value; 
       OnPropertyChanged("DisplayMessage"); 

      } 
     } 

     public string DisplayMessageForegroundColor 
     { 
      get 
      { 
       return m_displayMessageForegroundColor; 
      } 
      set 
      { 
       m_displayMessageForegroundColor = value; 
       OnPropertyChanged("DisplayMessageForegroundColor"); 

      } 
     } 

MainWindow.xaml

<Label Content="{Binding DisplayMessage}" Foreground="{Binding DisplayMessageForegroundColor}" Grid.Column="1" HorizontalAlignment="Left" Height="33" Margin="14,660,0,0" Grid.Row="1" 
      VerticalAlignment="Top" Width="693" Grid.ColumnSpan="3"/> 

但是,这似乎并没有工作。虽然在app.xaml.cs中的方法被调用,我没有看到显示错误m在UI上发送消息。请问这里有什么不对吗? (我可以在MainWindowViewModel中设置DisplayMessage和DisplayMessageForegroundColor属性时看到消息)。

请指教。

感谢。

+2

我猜MainWindowViewModel.Instance不是绑定到视图的视图模型的实例。 – ibebbs

+0

向我们展示如何将'MainWindowViewModel.Instance'赋值给'MainWindow.DataContext'。这可能是问题所在。 @ibebbs几乎肯定是正确的。 –

+0

你好...我在我的MainWindow.xaml文件中设置上下文---> ....这就是你需要吗?谢谢。 –

回答

2

问题是,你写了一个singleton视图模型,与单身人士Instance,但你不使用它。相反,你在你的XAML创建视图模型的一个新的不同实例:

<Window.DataContext> 
    <MainViewModel:MainWindowViewModel /> 
</Window.DataContext> 

,创建了MainWindowViewModel一个新的实例。如果你的XAML有<TextBox .../>,你认为世界上只有一个TextBox,你只是把它放在一个新的地方?当然不是。您正在创建一个新的TextBox。其他任何XAML元素也是如此。

修复很简单:首先,删除上面引用的那个Window.DataContext元素。

,静态单视图模型分配给DataContext代替:

<Window 
    ...etc... 
    xmlns:MainViewModel="clr-namespace:Whatever.Namespace.YourViewModel.IsIn" 
    DataContext="{x:Static MainViewModel:MainWindowViewModel.Instance}" 
    ...etc... 
    > 

或者:

<Window.DataContext> 
    <x:StaticExtension 
     Member="MainViewModel:MainWindowViewModel.Instance" /> 
</Window.DataContext> 

<x:StaticExtension ...是一回事{x:Static...System.Windows.Markup.StaticExtensionMarkupExtension的子类。如果其中的一个在类名上有Extension后缀,那么当您使用它作为大括号之间的标记扩展名时,XAML允许您省略名称的那部分名称。尝试这个;它会工作:

DataContext="{x:StaticExtension MainViewModel:MainWindowViewModel.Instance}" 

同样的事情。 BindingSystem.Windows.Data.Binding)也是MarkupExtension。这就是为什么你可以在XAML中的属性值来创建一个与花括号:

<TextBox Text="{Binding Foo}" /> 

Text="{Binding Foo}"创建的System.Windows.Data.Binding一个实例。但Binding在类名上没有Extension后缀。这不是要求,只是XAML提供的方便,如果你想使用它。

外带:无论何时在XAML中看到Property="{Identifier ...}"Identifier都是从System.Windows.Markup.MarkupExtension派生的类。它的实际名称可能是IdentifierIdentifierExtension,而大括号则是创建并初始化它的一个实例。

好的,回到你的bug。

让我们从中学习。

当你试图编写一个单例类时,你需要防止其他类创建它的实例,所以你不会得到这样的东西。做到这一点的最简单,最好的办法是让MainWindowViewModel的构造私有:

public class MainWindowViewModel : ViewModelBaseOrWhatever 
{ 
    // If MainWindowViewModel has no public constructors, no other class can create an 
    // instance of it. This is a requirement you need to enforce, so and you can make 
    // the compiler enforce it for you. If you had done this, the compiler would have 
    // found this bug for you as soon as you wrote it. 
    private MainWindowViewModel() 
    { 
     // ...whatever... 
    } 

    static MainWindowViewModel() 
    { 
     Instance = new MainWindowViewModel(); 
    } 

    public static MainWindowViewModel Instance { get; private set; } 
} 

单身

在单类的主题,这是明智的通过使构造私人行使其单性质,和在静态构造函数创建Instance

private MySingletonViewModel() 
{ 
    // stuff 
} 

public static MySingletonViewModel Instance { get; private set; } 

// Static constructor 
static MySingletonViewModel() 
{ 
    Instance = new MySingletonViewModel(); 
} 

当你这样做,编译器是在计划,它不会让你意外地创建第二个实例:

这里,编译器会抱怨:

'MySingletonViewModel.MySingletonViewModel()' 不可访问由于其保护级别。

你第一次看到你会说“呃?!”,但是对于大多数错误信息来说都是如此。

public SomeOtherClass() 
{ 
    var x = new MySingletonViewModel(); 
}