【问题标题】:Control Databinding to View not ViewModel in MVVM scenario在 MVVM 场景中控制数据绑定到 View 而不是 ViewModel
【发布时间】:2013-04-25 23:25:27
【问题描述】:

我已经使用 MVVM 模型工作了一周左右,我想我已经掌握了现在应该去哪里。请注意其中的“思考”。

我的视图 (MainWindow) 绑定到一个 ViewModel

_ViewModel = new MainViewModel();
this.DataContext = _ViewModel;

我有一些 ICommands 可以在 ViewModel 和随后的 Model 中工作,我觉得很好。

现在我从我的视图 (MainWindow) 中启动几个窗口,我在代码隐藏中执行这些窗口,因为它们都是纯粹的视图相关的东西。我正在尝试复制我在 View 中的 ViewModel 中的 ICommand 设置以简化我的生活,或者我是这么认为的。我有以下命令设置:

public ICommand comInitialiseWindows { get; private set; }

private bool _windowsactive = false;
public bool WindowsActive
{
    get { return _windowsactive; }
    set { SetProperty(ref _windowsactive, value); }
}
public bool comInitialiseWindows_CAN()
{
    return !_windowsactive;
}
private void comInitialiseWindows_DO()
{
    ... Code to do the window creation, etc.
}

我在 MainWindow 代码中有这个中继命令:

comInitialiseWindows = new RelayCommand(() => comInitialiseWindows_DO(), comInitialiseWindows_CAN);

如果我把它放在 ViewModel 中,除了创建窗口之外,它还可以作为一种享受,但由于它与 View 相关,我并不感到惊讶。

所以问题是当我单击按钮时代码没有运行。我猜测 XAML 绑定到 ViewModel,但是如果不将每个按钮的绑定设置为代码隐藏中的 MainWindow,我无法解决这个问题。我曾假设以下方法会起作用,但它不起作用:

<Button x:Name="ribbutLayoutWindows"                                     
    Command="{Binding local:comInitialiseWindows}" 
    IsEnabled="{Binding local:comInitialiseWindows_CAN}"/>

我很确定我只是没有在某处得到什么。或者我试图使普通按钮单击就足够的事情变得过于复杂,因为它只是查看。

有什么建议吗?

【问题讨论】:

  • 为什么“启动几个窗口”纯视图相关?您的视图模型包含视图逻辑,视图只是为用户可视化视图模型。我使用从视图模型调用的服务来启动新的对话框或窗口。顺便说一句,您应该检查是否需要新窗口,或者只是为您的主视图切换用户控件。

标签: c# wpf mvvm binding icommand


【解决方案1】:

有两种可能:

通过 ViewModel: 您可以在 ViewModel 上公开一个属性:

class MainViewModel
{
    ICommand comInitialiseWindows  {get; set;}
}

在你的主窗口中:

MainViewModel vm = this.DataContext as MainViewModel;
vm.comInitialiseWindows  = new RelayCommand(() => comInitialiseWindows_DO(), comInitialiseWindows_CAN);

XAML:

<Button x:Name="ribbutLayoutWindows" Command="{Binding comInitialiseWindows}" />

注意:您不需要绑定IsEnabled 属性。 WPF 将为您处理并自动调用您的 ICommand 的 CanExecute 方法。

通过 DependencyProperty

在你的代码隐藏中声明这个dependecyProperty:

public ICommand comInitialiseWindows
{
    get { return (ICommand)GetValue(MyPropertyProperty); }
    set { SetValue(MyPropertyProperty, value); }
}

public static readonly DependencyProperty comInitialiseWindowsProperty = 
    DependencyProperty.Register("comInitialiseWindows", typeof(ICommand), typeof(MainWindow), new PropertyMetadata(null));

在代码隐藏中赋值:

comInitialiseWindows = new RelayCommand(() => comInitialiseWindows_DO(), comInitialiseWindows_CAN);

之后,您需要打破 XAML 中的数据上下文。首先,为您的主页命名:

<Window x:Class="Web_Media_Seeker_WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:local="clr-namespace:Web_Media_Seeker_WPF"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="myWindow"
        Title="MainWindow" Height="350" Width="525">

然后声明你的绑定如下:

<Button x:Name="ribbutLayoutWindows" Command="{Binding comInitialiseWindows, ElementName=myWindow}" />

【讨论】:

  • 感谢您的回复。除非我在您的第一个示例中弄错了,否则“_DO”将在 ViewModel 中。我已经尝试过了,它可以正常工作,只是我需要在 MainWindow 代码隐藏中进行窗口处理。我看过第二个例子,但它似乎根本不适合我。我猜你把“MyPropertyProperty”放在哪里,这应该是 comInitialiseWindowsProperty,但是“_DO”代码不会触发。
  • 不,在第一个示例中,您的 VM 中唯一的东西就是属性。命令的方法和创建在MainPage中。
  • 啊。我会试试看。在第二个示例中,我在输出窗口中收到“找不到绑定源”消息,因此显然某处有问题。
  • 甜蜜。感谢第一个立即工作。我的布尔值在某个地方错了,因为错误的按钮被禁用了 ;-) 谢谢...
猜你喜欢
  • 2013-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
  • 2011-01-21
  • 1970-01-01
  • 2014-08-05
相关资源
最近更新 更多