WPF MVVM:如何关闭一个窗口

点击时,我有一个Button可以关闭我的窗口:

<Button x:Name="buttonOk"  IsCancel="True">Ok</Button>

这很好,直到我添加一个Command Button ie

<Button x:Name="buttonOk" 
        Command="{Binding SaveCommand}" 
        IsCancel="True">Ok</Button>

现在它不能关闭,大概是因为我正在处理Command 。 我可以通过将EventHandler放入并调用this.Close()即可解决此问题

<Button x:Name="buttonOk" 
        Click="closeWindow" 
        Command="{Binding SaveCommand}" 
        IsCancel="True">Ok</Button>

但现在我的代码中有代码,即方法SaveCommand 。 我正在使用MVVM模式,并且SaveCommand是我的代码中唯一的代码。

我怎样才能做到这一点,以便不使用代码?


我刚刚完成了关于这个话题的博客文章。 简而言之,使用getset访问器将Action属性添加到ViewModel。 然后从View构造函数中定义Action 。 最后,在应该关闭窗口的绑定命令中调用您的操作。

在ViewModel中:

public Action CloseAction  { get; set;}

并在View构造函数中:

private View()
{
    InitializeComponent();
    ViewModel vm = new ViewModel();
    this.DataContext = vm;
    if ( vm.CloseAction == null )
        vm.CloseAction = new Action(this.Close);
}

最后,无论应该关闭窗口的任何绑定命令,我们都可以简单地调用

CloseAction(); // Calls Close() method of the View

这对我很有用,看起来像一个相当优雅的解决方案,并为我节省了一堆编码。


不幸的是,显示窗口在MVVM中是一个真正的痛苦,因此您需要做相当多的基础设施工作或使用像Cinch这样的MVVM框架。 如果你想投入时间做自己,这里有一个关于Cinch如何做的链接。

它很好,你试图让任何逻辑摆脱视图,但它真的不是世界的尽头,如果你这样做。 在这种情况下,听起来不会造成太多问题。


正如有人评论的,我发布的代码不是MVVM友好的,第二种解决方案如何?

第一,不是MVVM解决方案(我不会删除这个作为参考)

XAML:

<Button Name="okButton" Command="{Binding OkCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">OK</Button>

视图模型:

public ICommand OkCommand
{
    get
    {
        if (_okCommand == null)
        {
            _okCommand = new ActionCommand<Window>(DoOk, CanDoOk);
        }
        return _okCommand ;
    }
}

void DoOk(Window win)
{
    // Your Code
    win.DialogResult = true;
    win.Close();
}

bool CanDoOk(Window win) { return true; }

第二,可能更好的解决方案:使用附加行为

XAML

<Button Content="Ok and Close" Command="{Binding OkCommand}" b:CloseOnClickBehaviour.IsEnabled="True" />

查看模型

public ICommand OkCommand
{
    get { return _okCommand; }
}

行为类与此类似的东西:

public static class CloseOnClickBehaviour
{
    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached(
            "IsEnabled",
            typeof(bool),
            typeof(CloseOnClickBehaviour),
            new PropertyMetadata(false, OnIsEnabledPropertyChanged)
        );

    public static bool GetIsEnabled(DependencyObject obj)
    {
        var val = obj.GetValue(IsEnabledProperty);
        return (bool)val;
    }

    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }

    static void OnIsEnabledPropertyChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs args)
    {
        var button = dpo as Button;
        if (button == null)
            return;

        var oldValue = (bool)args.OldValue;
        var newValue = (bool)args.NewValue;

        if (!oldValue && newValue)
        {
            button.Click += OnClick;
        }
        else if (oldValue && !newValue)
        {
            button.PreviewMouseLeftButtonDown -= OnClick;
        }
    }

    static void OnClick(object sender, RoutedEventArgs e)
    {
        var button = sender as Button;
        if (button == null)
            return;

        var win = Window.GetWindow(button);
        if (win == null)
            return;

        win.Close();
    }

}
链接地址: http://www.djcxy.com/p/56113.html

上一篇: WPF MVVM: How to close a window

下一篇: /ViewModel for a Task or Dialog look like?