2016-11-09 26 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(); 
}