[英]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.