开发者

MVVM Window / Control Operations

I'm building a WPF MVVM application and I'd like to keep what I can conforming to MVVM (I know some stuff is over-engineering, putting a best effort here though).

I've run into a small dillema, I need to Hide / Close a window based on some logic in one the the methods in the view model.

I can't for the life of me come up with a reliable way to do it. I've bound a Visibility property to the window's Visibility DP, which works (sorta) but how would I call Close() on the dialog?

I'm using View-First MVVM so the view model has no knowledge of the view, the开发者_如何学运维 view instantiates a view-model (through DI/IoC) and sets it as the DataContext.

Commands work the wrong way, events are out of the question unless I bind to it in code behind which is something id rather not do if there's an MVVM way to do it that isn't entirely convoluted.

Any ideas from the greater SO community?

Or maybe I'm missing something about MVVM in general? Either way, let me know :o


As is often the case, there are many ways to skin this cat.

One way to do this without codebehind in the view is to use an attached behaviour, such as the following:

public static class CloseBehavior 
{
    public static bool GetCloseWhen(DependencyObject obj)
    {
        return (bool)obj.GetValue(CloseWhenProperty);
    }

    public static void SetCloseWhen(DependencyObject obj, bool value)
    {
        obj.SetValue(CloseWhenProperty, value);
    }

    public static readonly DependencyProperty CloseWhenProperty =
        DependencyProperty.RegisterAttached(
            "CloseWhen", typeof(bool), typeof(CloseBehavior), 
            new UIPropertyMetadata(OnCloseWhenChanged));
    // the lone parameter in the UIPropertyMetadata is a callback
    // for when the property value changes

    static void OnCloseWhenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // if false, we're not concerned with it
        if(!(bool)e.NewValue) return;

       // if attached to something other than a window, this doesn't make sense
        var win = d as Window;

        if(d == null) return;

            // close the window
        win.Close();
    }
}

In your XAML:

<Window x:Class="WpfApplication1.Window1"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication1" 

     local:CloseBehavior.CloseWhen="{Binding ViewModelWorkComplete}"
>
<! -- content -->
</Window>

Where ViewModelWorkComplete is just a boolean property in the view model.

The effect is that when the viewmodel sets ViewModelWorkComplete to true (and raises the appropriate INotifyPropertyChanged event), the window will be closed.


What's wrong about events and subscribing in code-behind? Closing window is a presentation-specific thing and it certainly belongs to the View.

It's testability and separation of concerns that are primary goals here, and you can easily verify that particular event is raised by ViewModel.


Using the Mediator pattern or other event handling mechanisms, you can raise certain viewmodel events (maybe "SaveDone" or "NoDataRemaining", etc). Then make your view to listen to these events; based on them, the window can decide to close itself.

If there is a more explicit way for the user to say "Close" (such as by clicking a close button in the window), hopefully that can be handled in the window exclusively.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜