MVVM - 从视图模型关闭窗口

时间:2018-01-02 12:42:13

标签: c# wpf mvvm binding prism

在我的应用程序中,我使用棱镜并尝试实现以下概念:

有一个通信窗口,可以有两个可能的用户控件。我有窗口和用户控件的ViewModels。 在每个用户控件中我都有一些按钮。对于某些按钮,我需要在ViewModel中执行一些逻辑,当逻辑完成时,关闭父窗口。 我试图将parant窗口作为命令参数发送,如下所示:

CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"

在viewModel中使用以下代码关闭窗口:

// Create the command
OpenChannelCommand = new RelayCommand(OpenChannel, IsValidFields);
...
private void OpenChannel()
{
  // do some logic...
  CloseWindow();
}
private GalaSoft.MvvmLight.Command.RelayCommand<object> _closeCommand;
private GalaSoft.MvvmLight.Command.RelayCommand<object> CloseWindow()
{
    _closeCommand = new GalaSoft.MvvmLight.Command.RelayCommand<object>((o) => ((Window)o).Close(), (o) => true);
    return _closeCommand;
}

但窗户仍未关闭。

编辑:

用户控件XAML代码为:

<Button Content="Open Channel" Command="{Binding OpenChannelCommand}" 
                CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/>

用户控件ViewModel代码为:

public RelayCommand OpenChannelCommand { get; set; } 
ctor() 
{
   OpenChannelCommand = new RelayCommand(OpenChannel, IsValidFields);
}     
private void OpenChannel() 
{    
   // logic 
   CloseWindow(); 
}
private GalaSoft.MvvmLight.Command.RelayCommand<object> CloseWindow()
{
    _closeCommand = new GalaSoft.MvvmLight.Command.RelayCommand<object>((o) => ((Window)o).Close(), (o) => true);
    return _closeCommand;
 }

这是我目前尝试的完整实现。 当设置一个断点到CloseWindow方法时,它在视图modet初始化时命中,并在按钮单击命令中再次调用它之后没有做任何事情。

1 个答案:

答案 0 :(得分:1)

关闭窗口是视图的责任,视图模型应该对它一无所知。难怪你变得纠缠不清。如果在“按钮​​逻辑”运行时不需要窗口停留在屏幕上,那么只需使用Prism中的CompositeCommand(我不喜欢它,因为它使用代码隐藏,但无论如何)或等效于将两个命令绑定到按钮。另一方面,如果你需要在“按钮逻辑”运行时将窗口保持在屏幕上,例如要显示进度,如果您的视图模型反映了这一点,那么您可以向视图模型添加bool IsButtonLogicComplete属性(不要忘记INotifyPropertyChanged)并将窗口的“关闭”状态绑定到此属性像这样的附属财产/行为:

public static class AttachedProperties
{
    // in Visual Studio, the `propa` snippet inserts the boilerplate
    public static DependencyProperty ForceCloseProperty =
        DependencyProperty.RegisterAttached ("ForceClose",
        typeof (bool), typeof (AttachedProperties), new UIPropertyMetadata (false, (d, e) =>
        {
            var w  = d as Window ;
            if (w != null && (bool) e.NewValue)
            {
                w.DialogResult = true ;
                w.Close () ;
            }
        })) ;

    public static bool GetForceClose (DependencyObject obj)
    {
        return (bool) obj.GetValue (ForceCloseProperty) ;
    }

    public static void SetForceClose (DependencyObject obj, bool value)
    {
        obj.SetValue (ForceCloseProperty, value) ;
    }
}

<!-- in .xaml -->
<Window
  xmlns:local="clr-namespace:YourNamespace"
  local:AttachedProperties.ForceClose="{Binding IsButtonLogicComplete}" ...

这将使您的视图与您的视图模型问题保持良好分离。