app. example .cs与MainViewmodel通信的问题

本文关键字:通信 问题 MainViewmodel example cs app | 更新日期: 2023-09-27 18:17:06

我在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. example .cs中的方法正在被调用,但我没有看到在UI上显示的错误消息。请问这里有什么问题吗?(当我从MainWindowViewModel中设置DisplayMessage和DisplayMessageForegroundColor属性时,我能够看到消息)。

请建议。

谢谢。

app. example .cs与MainViewmodel通信的问题

问题是你写了一个单例视图模型,有一个单例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}"

一样。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派生的类。它的实际名称可能是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()'由于其保护级别而无法访问。

第一次看到时,您会说"huh?!",但大多数错误消息都是这样。

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