[英]Issue with app.xaml.cs to MainViewmodel communication
我在wpf App.xaml.cs文件中遵循以下代碼:
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中的方法,但我沒有在UI上看到顯示消息的錯誤,請問這里可能出什么問題了? (不過,從MainWindowViewModel內設置DisplayMessage和DisplayMessageForegroundColor屬性時,我可以看到該消息)。
請指教。
謝謝。
問題是您編寫了具有singleton Instance
的singleton視圖模型,但隨后不使用它。 而是在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.StaticExtension
是MarkupExtension
子類。 如果其中之一在類名上具有Extension
后綴,則XAML允許您在將其用作花括號之間的標記擴展名時忽略名稱的該部分。 嘗試這個; 它會工作:
DataContext="{x:StaticExtension MainViewModel:MainWindowViewModel.Instance}"
一樣。 Binding
( System.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
的類。 它的實際名稱可能是Identifier
或IdentifierExtension
,花括號正在創建和初始化它的實例。
好,回到您的錯誤。
讓我們從中學習。
當您嘗試編寫單例類時,需要防止其他類創建它的實例,因此您最終不會遇到這樣的事情。 最簡單,最好的方法是將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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.