C# 如何在MainWindow中的StatusBarItem中更新WPF UserControl属性以形成另一个UserControl,两者都具有不同的数据上下文?

C# 如何在MainWindow中的StatusBarItem中更新WPF UserControl属性以形成另一个UserControl,两者都具有不同的数据上下文?,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我试着寻找类似问题的答案,但我找不到任何适合这种情况的答案 我有一个类似这样的主窗口(省略了某些部分): 和两个用户控件: <UserControl x:Class="test.Views.StatusView" xmlns:local="clr-namespace:test.Views" xmlns:ViewModels="clr-namespace:test.ViewModels"> <UserControl.DataContext>

我试着寻找类似问题的答案,但我找不到任何适合这种情况的答案

我有一个类似这样的主窗口(省略了某些部分):

和两个用户控件:

<UserControl x:Class="test.Views.StatusView"
     xmlns:local="clr-namespace:test.Views"
     xmlns:ViewModels="clr-namespace:test.ViewModels">
    <UserControl.DataContext>
        <ViewModels:StatusViewModel/>
    </UserControl.DataContext>
    <Grid>
        <Border>
            <TextBlock Text="{Binding Status}" />
        </Border>
    </Grid>
</UserControl>
以及:

每个UserControl都将自己的ViewModel设置为DataContext:

using System;
using System.ComponentModel;

namespace test.ViewModels
{
    class StatusViewModel : INotifyPropertyChanged
    {
        private string _status = string.Empty;
        public string Status
        {
            get { return _status; }
            set { _status = value; OnPropertyChanged("Status"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        public StatusViewModel() { }
    }
}
以及:

正如您从代码配置文件中看到的,视图中有MouseEnter和MouseLeave事件,我想在StatusView中设置TextBlock.Text值(通过它的ViewModel.Status属性)

现在这里没有显示,但其他类也应该能够使用相同的原理,以线程安全的方式更新状态栏的值

我该如何做到这一点

我曾想过使用DependencyProperty或委托和事件,但不知道如何实现,因为目前,两个用户控件(和其他控件)都是通过MainWindow中的XAML实例化的,而不是通过代码隐藏。我认为,这就是应该怎么做的(如果我要遵循MVVM并将工作分离——设计师在设计,而程序员在编程),但这正是我不知道如何解决这个问题的原因


谢谢您的帮助。

我强烈建议您使用MVVM Light

您可以使用MVVM Light Messenger。它是一个允许在对象之间交换消息的类。Messenger类主要用于在viewmodels之间发送消息:

PS:我还建议使用命令绑定而不是事件处理程序(不像MVVM)

<UserControl x:Class="test.Views.StatusView"
     xmlns:local="clr-namespace:test.Views"
     xmlns:ViewModels="clr-namespace:test.ViewModels">
    <UserControl.DataContext>
        <ViewModels:StatusViewModel/>
    </UserControl.DataContext>
    <Grid>
        <Border>
            <TextBlock Text="{Binding Status}" />
        </Border>
    </Grid>
</UserControl>
<UserControl x:Class="test.Views.ProfileView"
     xmlns:local="clr-namespace:test.Views"
     xmlns:ViewModels="clr-namespace:test.ViewModels" MouseEnter="UserControl_MouseEnter" MouseLeave="UserControl_MouseLeave">
    <UserControl.DataContext>
        <ViewModels:ProfileViewModel/>
    </UserControl.DataContext>
    <Grid>
        //    some stuff done here
    </Grid>
</UserControl>
using System.Windows.Controls;

namespace test.Views
{
    public partial class StatusView : UserControl
    {
        public StatusView()
        {
            InitializeComponent();
        }
    }
}
using System.Windows.Controls;

namespace test.Views
{
    public partial class ProfileView : UserControl
    {
        public ProfileView()
        {
            InitializeComponent();
        }

        private void UserControl_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
        {
            //    Update status bar text
        }

        private void UserControl_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        {
            //    Update status bar text
        }
    }
}
using System;
using System.ComponentModel;

namespace test.ViewModels
{
    class StatusViewModel : INotifyPropertyChanged
    {
        private string _status = string.Empty;
        public string Status
        {
            get { return _status; }
            set { _status = value; OnPropertyChanged("Status"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        public StatusViewModel() { }
    }
}
using System;

namespace test.ViewModels
{
    class ProfileViewModel

        public ProfileViewModel() { }

        //    some stuff done here
    }
}