如何更新MainWindow中StatusBarItem中的WPF UserControl属性,形成另一个具有不同DataContexts的UserControl?

时间:2016-11-24 11:29:35

标签: c# wpf xaml mvvm

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

我有一个看起来像这样的MainWindow(某些部分被省略):

<Window x:Class="test.MainWindow"
    xmlns:local="clr-namespace:test"
    xmlns:Views="clr-namespace:test.Views">
    <Grid>
        <DockPanel>
            <StatusBar>
                <StatusBarItem>
                    <Views:ProfileView />
                </StatusBarItem>
                <Separator />
                <StatusBarItem>
                    <Views:StatusView />
                </StatusBarItem>
            </StatusBar>
        </DockPanel>
    </Grid>
</Window>

代码隐藏:

using System.Windows;

namespace test
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        //    some stuff done here
    }
}

和两个UserControl:

<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
        }
    }
}

每个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() { }
    }
}

using System;

namespace test.ViewModels
{
    class ProfileViewModel

        public ProfileViewModel() { }

        //    some stuff done here
    }
}

从代码中可以看出,ProfileView上有MouseEnter和MouseLeave事件,我想在StatusView中设置TextBlock.Text值(通过它的ViewModel.Status属性)。

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

我如何实现这一目标?

我想过使用DependencyPropertyes或Delegates and Events但是,不知道怎么做,因为目前,UserControls(和其他)都是通过MainWindow中的XAML实例化的,而不是通过代码隐藏实例化的。这就是我认为应该如何完成的(如果我跟随MVVM并分离工作 - 设计师正在设计而程序员正在编程)但是,这正是我不知道的原因如何解决这个问题。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我强烈建议使用MVVM Light。

您可以使用MVVM Light Messenger。它是一个允许在对象之间交换消息的类。 Messenger类主要用于在视图模型之间发送消息: http://dotnetpattern.com/mvvm-light-messenger

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