1

我正在开发一个 Surface WPF 项目,我们尝试在其中实现 MVVM 模式。在这个项目中,我们正在构建一些我们绑定到不同视图模型的自定义控件。

例如,我们有一个设置控件,它有一个设置视图模型,我们有一个主视图模型,它是“整体”视图模型。

在我们的 surfacewindows.xaml 页面中,我们使用 mvvm-light 中的视图模型定位器将数据上下文设置为主视图模型。此外,在我们的 surfacewindow.xaml 中,我们添加了设置控件,并在控件上将 datacontext 设置为设置视图模型。

现在我们需要两个视图模型相互交互:当前的情况是我们需要设置设置控件的可见性。我们在主视图模型上有一个属性,它是一个布尔值 (IsSettingsControlVisible),它通过使用转换器将布尔值转换为可见性对象来绑定到控件的 Visibility 属性。

当我们需要通过单击设置控件上的关闭按钮将可见性设置为不可见时,现在出现了问题。因为我们已经将控件上的数据上下文设置为设置视图模型,所以我们无法访问主视图模型。

到目前为止,我们所想到的是将设置视图模型作为属性添加到主视图模型中,并从设置控件中删除数据上下文。在设置控件中,我们将使用绑定作为 SettingsProperty.Property。比我们也可以从设置控件访问主视图模型。那有意义吗?有没有更好的方法来进行这种互动?

我真的很想听听你关于如何让这些互动发生的想法。

4

3 回答 3

1

我倾向于使用使用 Castle Windsor 构建的视图模型图。顶层视图模型使用构造函数注入来接收它需要的下一层视图模型。在视图中,我将内容呈现器绑定到视图模型上的属性以创建相应的视图图。

这样做,父子视图模型很容易通信,但兄弟或更远的视图模型通信有点困难。

在这些情况下,我倾向于使用事件聚合器或 Messenger 来允许视图模型进行通信。

于 2012-06-06T09:01:23.073 回答
1

由于您已经在使用 MVVMLight,我建议您使用 MVVM Light 工具包 Messenger 系统。它用于 ViewModel 之间的消息交换。背后的概念是Mediator pattern不同对象在彼此不认识的情况下交换信息。

这是一个例子:

在 SettingsViewModel 中注册一个告诉显示设置对话框的事件

public SettingsViewModel()
{
  Messenger.Default.Register<ShowSettingsMessage>(this, ShowSettingsDialog);
}

private void ShowSettingsDialog(ShowSettingsMessage showSettingsMessage)
{
  // Set the visibility:
  this.IsVisible = showSettingsMessage.Content;
}

在您的 MainViewModel 中,您发送通知,包裹在一条消息中:

// make the settings visible, e.g. the button click command:    
Messenger.Default.Send(new ShowSettingsMessage(true));

这是消息:

// the message:
public class ShowSettingsMessage : GenericMessage<bool>
   {
     public ShowSettingsMessage(bool isVisible)
       : base(isVisible)
     {  }
   }

我不建议创建SettingsViewModela 的属性,Mainviewmodel因为您失去了SettingsViewModel在不同上下文中使用的可能性,甚至删除/交换它。

于 2012-06-06T09:26:17.547 回答
0

尝试在名为 IsSettingControlVisible 的 Settings 控件上创建一个依赖属性,并将其与父 viewModel 绑定。

编辑:

public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }


        public int MyProperty
        {
            get { return (int)GetValue(MyPropertyProperty); }
            set { SetValue(MyPropertyProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MyPropertyProperty =
            DependencyProperty.Register("MyProperty", typeof(int), typeof(UserControl1), new UIPropertyMetadata(0));
    }

并像这样使用它...

 <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfApplication1"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <local:UserControl1 MyProperty="{Binding Path=ParentViewModelProperty, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" />
        </Grid>
    </Window>
于 2012-06-06T09:00:37.263 回答