c# - app.xaml.cs 与 MainViewmodel 通信的问题

标签 c# wpf mvvm

我的 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");

            }
        }

主窗口.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 属性时,我能够看到该消息)。

请指教。

谢谢。

最佳答案

问题是你写了一个单例 View 模型,带有一个单例 Instance ,但是你不使用它。相反,您在 XAML 中创建 View 模型的新不同实例:

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

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

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

然后将静态单例 View 模型分配给 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}"

一样。 Binding ( System.Windows.Data.Binding ) 是 MarkupExtension也是。这就是为什么您可以在 XAML 中的属性值中使用花括号创建一个:
<TextBox Text="{Binding Foo}" />
Text="{Binding Foo}"创建 System.Windows.Data.Binding 的实例.但是Binding没有 Extension类名的后缀。这不是必需的,它只是 XAML 提供的一种便利,如果您愿意使用它。

外卖:每当你看到Property="{Identifier ...}"在 XAML 中,Identifier是一个派生自 System.Windows.Markup.MarkupExtension 的类.它的实际名称可能是 IdentifierIdentifierExtension ,并且那个花括号的东西正在创建和初始化它的一个实例。

好的,回到你的错误。

让我们从中学习。

当你尝试编写一个单例类时,你需要防止其他类创建它的实例,所以你不会得到这样的东西。最简单和最好的方法是制作 MainWindowViewModel的构造函数私有(private):
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; }
}

单例

关于单例类,明智的做法是通过将构造函数设为私有(private)并创建 Instance 来强制它们的单例性质。在静态构造函数中:
private MySingletonViewModel()
{
    //  stuff
}

public static MySingletonViewModel Instance { get; private set; }

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

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

在这里,编译器会提示:

'MySingletonViewModel.MySingletonViewModel()' is inaccessible due to its protection level.



第一次看到你会说“嗯?!”,但大多数错误消息都是如此。
public SomeOtherClass() 
{
    var x = new MySingletonViewModel();
}

关于c# - app.xaml.cs 与 MainViewmodel 通信的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40516008/

相关文章:

c# - C#中的静态构造函数到底是什么?

c# - 功能区 ApplicationMenu AuxilaryPane Size

c# - 如何使用 INotifyDataErrorInfo 接口(interface)验证 Observable 集合

ios - MVVM、依赖注入(inject)和过多的构造函数参数

c# - 为什么collection1 和collection2 有相同的值?

c# - 同步 Web Api 和响应时间取决于线程和请求计数

c# - 用作基类/接口(interface)时验证 Moq 方法调用

c# - 如何对 WebBrowser 附加属性进行单元测试?

Silverlight MVVM 绑定(bind)似乎不起作用

c# - 我如何在 C# 中访问硬盘驱动器中的所有分区