Fix conductors, view binding, and add the WindowConductor

This commit is contained in:
Antony Male 2014-02-22 21:24:36 +00:00
parent e972f2d054
commit 9da8461004
7 changed files with 103 additions and 15 deletions

View File

@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet", "..\Stylet\Stylet.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.Hello", "Stylet.Samples.Hello\Stylet.Samples.Hello.csproj", "{6C7FBB21-52AC-4333-A42A-9F5E9D048621}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stylet.Samples.TabNavigation", "Stylet.Samples.TabNavigation\Stylet.Samples.TabNavigation.csproj", "{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -21,6 +23,10 @@ Global
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6C7FBB21-52AC-4333-A42A-9F5E9D048621}.Release|Any CPU.Build.0 = Release|Any CPU
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A4E2DAD-AE68-4A82-8FA8-407DB74D6FBE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -27,12 +27,10 @@ namespace Stylet
newItem = this.EnsureItem(newItem);
if (this.IsActive)
{
ScreenExtensions.TryActivate(newItem);
this._activeItem = newItem;
this.NotifyOfPropertyChange(() => this.ActiveItem);
}
this._activeItem = newItem;
this.NotifyOfPropertyChange(() => this.ActiveItem);
}
protected override void OnActivate()

View File

@ -3,12 +3,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace Stylet
{
public interface IViewAware
{
void AttachView(object view);
UIElement View { get; }
void AttachView(UIElement view);
}
public interface IActivate

View File

@ -13,7 +13,7 @@ namespace Stylet
public virtual void TryClose(bool? dialogResult = null)
{
// TODO: Check for parent conductor
var viewWindow = this.view as Window;
var viewWindow = this.View as Window;
if (viewWindow != null)
{
if (dialogResult != null)
@ -22,7 +22,7 @@ namespace Stylet
return;
}
var viewPopover = this.view as Popup;
var viewPopover = this.View as Popup;
if (viewPopover != null)
{
viewPopover.IsOpen = false;
@ -98,7 +98,7 @@ namespace Stylet
handler(this, new DeactivationEventArgs() { WasClosed = close });
if (close)
this.view = null;
this.View = null;
}
protected virtual void OnDeactivate(bool close) { }
@ -107,14 +107,14 @@ namespace Stylet
#region IViewAware
private object view;
public UIElement View { get; private set; }
void IViewAware.AttachView(object view)
void IViewAware.AttachView(UIElement view)
{
if (this.view != null)
if (this.View != null)
throw new Exception(String.Format("Tried to attach View {0} to ViewModel {1}, but it already has a view attached", view.GetType().Name, this.GetType().Name));
this.view = view;
this.View = view;
var viewAsFrameworkElement = view as FrameworkElement;
if (viewAsFrameworkElement != null)

View File

@ -51,8 +51,17 @@ namespace Stylet
if (e.NewValue != null)
{
var view = ViewLocator.LocateForModel(e.NewValue);
ViewModelBinder.Bind(view, e.NewValue);
UIElement view;
var viewModelAsViewAware = e.NewValue as IViewAware;
if (viewModelAsViewAware != null && viewModelAsViewAware.View != null)
{
view = viewModelAsViewAware.View;
}
else
{
view = ViewLocator.LocateForModel(e.NewValue);
ViewModelBinder.Bind(view, e.NewValue);
}
SetContentProperty(targetLocation, view);
}

View File

@ -9,7 +9,7 @@ namespace Stylet
{
public static class ViewModelBinder
{
public static void Bind(DependencyObject view, object viewModel)
public static void Bind(UIElement view, object viewModel)
{
View.SetTarget(view, viewModel);

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -49,6 +50,8 @@ namespace Stylet
view.Owner = owner;
}
new WindowConductor(view, viewModel);
return view;
}
@ -60,5 +63,75 @@ namespace Stylet
var active = Application.Current.Windows.OfType<Window>().Where(x => x.IsActive).FirstOrDefault() ?? Application.Current.MainWindow;
return active == window ? null : active;
}
class WindowConductor
{
private readonly Window window;
private readonly object viewModel;
public WindowConductor(Window window, object viewModel)
{
this.window = window;
this.viewModel = viewModel;
var viewModelAsActivate = viewModel as IActivate;
if (viewModelAsActivate != null)
viewModelAsActivate.Activate();
var viewModelAsDeactivate = viewModel as IDeactivate;
if (viewModelAsDeactivate != null)
{
window.Closed += this.Closed;
viewModelAsDeactivate.Deactivated += this.Deactivated;
}
if (viewModel is IGuardClose)
window.Closing += this.Closing;
}
private void Closed(object sender, EventArgs e)
{
var viewModelAsDeactivate = (IDeactivate)this.viewModel;
this.window.Closed -= this.Closed;
this.window.Closing -= this.Closing; // Not sure this is required
viewModelAsDeactivate.Deactivated -= this.Deactivated;
viewModelAsDeactivate.Deactivate(true);
}
private void Deactivated(object sender, DeactivationEventArgs e)
{
if (!e.WasClosed)
return;
this.window.Closed -= this.Closed;
this.window.Closing -= this.Closing;
((IDeactivate)this.window).Deactivated -= this.Deactivated;
this.window.Close();
}
private async void Closing(object sender, CancelEventArgs e)
{
if (e.Cancel)
return;
// See if the task completed synchronously
var task = ((IGuardClose)this.viewModel).CanCloseAsync();
if (task.IsCompleted)
{
e.Cancel = !task.Result;
}
else
{
e.Cancel = true;
if (await task)
{
this.window.Closing -= this.Closing;
this.window.Close();
}
}
}
}
}
}