mirror of https://github.com/AMT-Cheif/Stylet.git
138 lines
4.2 KiB
C#
138 lines
4.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Data;
|
|
using System.Windows.Navigation;
|
|
|
|
namespace Stylet
|
|
{
|
|
public interface IWindowManager
|
|
{
|
|
void ShowWindow(object viewModel);
|
|
bool? ShowDialog(object viewModel);
|
|
}
|
|
|
|
public class WindowManager : IWindowManager
|
|
{
|
|
public void ShowWindow(object viewModel)
|
|
{
|
|
this.CreateWindow(viewModel, false).Show();
|
|
}
|
|
|
|
public bool? ShowDialog(object viewModel)
|
|
{
|
|
return this.CreateWindow(viewModel, true).ShowDialog();
|
|
}
|
|
|
|
private Window CreateWindow(object viewModel, bool isDialog)
|
|
{
|
|
var view = ViewLocator.LocateForModel(viewModel) as Window;
|
|
if (view == null)
|
|
throw new Exception(String.Format("Tried to show {0} as a window, but it isn't a Window", view.GetType().Name));
|
|
|
|
ViewModelBinder.Bind(view, viewModel);
|
|
|
|
var haveDisplayName = viewModel as IHaveDisplayName;
|
|
if (haveDisplayName != null)
|
|
{
|
|
var binding = new Binding("DisplayName") { Mode = BindingMode.TwoWay };
|
|
view.SetBinding(Window.TitleProperty, binding);
|
|
}
|
|
|
|
if (isDialog)
|
|
{
|
|
var owner = this.InferOwnerOf(view);
|
|
if (owner != null)
|
|
view.Owner = owner;
|
|
}
|
|
|
|
new WindowConductor(view, viewModel);
|
|
|
|
return view;
|
|
}
|
|
|
|
private Window InferOwnerOf(Window window)
|
|
{
|
|
if (Application.Current == null)
|
|
return null;
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|