Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 51 additions & 30 deletions MahApps.Metro/Controls/Dialogs/DialogCoordinator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

Expand All @@ -9,13 +10,11 @@ public class DialogCoordinator : IDialogCoordinator
/// <summary>
/// Gets the default instance if the dialog coordinator, which can be injected into a view model.
/// </summary>
public static readonly DialogCoordinator Instance = new DialogCoordinator();
public static readonly IDialogCoordinator Instance = new DialogCoordinator();

public Task<string> ShowInputAsync(object context, string title, string message, MetroDialogSettings settings = null)
{
var metroWindow = GetMetroWindow(context);

return metroWindow.ShowInputAsync(title, message, settings);
{
return ExecuteShowMessageDialogAsync(context, window => window.ShowInputAsync(title, message, settings));
}

public string ShowModalInputExternal(object context, string title, string message, MetroDialogSettings metroDialogSettings = null)
Expand All @@ -27,9 +26,7 @@ public string ShowModalInputExternal(object context, string title, string messag

public Task<LoginDialogData> ShowLoginAsync(object context, string title, string message, LoginDialogSettings settings = null)
{
var metroWindow = GetMetroWindow(context);

return metroWindow.ShowLoginAsync(title, message, settings);
return ExecuteShowMessageDialogAsync(context, window => window.ShowLoginAsync(title, message, settings));
}

public LoginDialogData ShowModalLoginExternal(object context, string title, string message, LoginDialogSettings settings = null)
Expand All @@ -41,9 +38,7 @@ public LoginDialogData ShowModalLoginExternal(object context, string title, stri

public Task<MessageDialogResult> ShowMessageAsync(object context, string title, string message, MessageDialogStyle style = MessageDialogStyle.Affirmative, MetroDialogSettings settings = null)
{
var metroWindow = GetMetroWindow(context);

return metroWindow.ShowMessageAsync(title, message, style, settings);
return ExecuteShowMessageDialogAsync(context, window => window.ShowMessageAsync(title, message, style, settings));
}

public MessageDialogResult ShowModalMessageExternal(object context, string title, string message, MessageDialogStyle style = MessageDialogStyle.Affirmative, MetroDialogSettings settings = null)
Expand All @@ -53,49 +48,75 @@ public MessageDialogResult ShowModalMessageExternal(object context, string title
return metroWindow.ShowModalMessageExternal(title, message, style, settings);
}

public Task<ProgressDialogController> ShowProgressAsync(object context, string title, string message,
bool isCancelable = false, MetroDialogSettings settings = null)
public Task<ProgressDialogController> ShowProgressAsync(object context, string title, string message, bool isCancelable = false, MetroDialogSettings settings = null)
{
var metroWindow = GetMetroWindow(context);

return metroWindow.ShowProgressAsync(title, message, isCancelable, settings);
return ExecuteShowMessageDialogAsync(context, window => window.ShowProgressAsync(title, message, isCancelable, settings));
}

public Task ShowMetroDialogAsync(object context, BaseMetroDialog dialog,
MetroDialogSettings settings = null)
public Task ShowMetroDialogAsync(object context, BaseMetroDialog dialog, MetroDialogSettings settings = null)
{
var metroWindow = GetMetroWindow(context);

return metroWindow.ShowMetroDialogAsync(dialog, settings);
return ExecuteShowMessageDialogAsync(context, window => window.ShowMetroDialogAsync(dialog, settings));
}

public Task HideMetroDialogAsync(object context, BaseMetroDialog dialog, MetroDialogSettings settings = null)
{
var metroWindow = GetMetroWindow(context);

return metroWindow.HideMetroDialogAsync(dialog, settings);
return ExecuteShowMessageDialogAsync(context, window => window.HideMetroDialogAsync(dialog, settings));
}

public Task<TDialog> GetCurrentDialogAsync<TDialog>(object context) where TDialog : BaseMetroDialog
{
return ExecuteShowMessageDialogAsync(context, window => window.GetCurrentDialogAsync<TDialog>());
}

private static Task ExecuteShowMessageDialogAsync(object context, Func<MetroWindow, Task> messageDialogFunc)
{
var metroWindow = GetMetroWindow(context);
if (metroWindow.CheckAccess())
{
return messageDialogFunc(metroWindow);
}
return metroWindow.Dispatcher.Invoke(new Func<Task>(() => messageDialogFunc(metroWindow))) as Task;
}

return metroWindow.GetCurrentDialogAsync<TDialog>();
private static Task<TResult> ExecuteShowMessageDialogAsync<TResult>(object context, Func<MetroWindow, Task<TResult>> messageDialogFunc)
{
var metroWindow = GetMetroWindow(context);
if (metroWindow.CheckAccess())
{
return messageDialogFunc(metroWindow);
}
return metroWindow.Dispatcher.Invoke(new Func<Task<TResult>>(() => messageDialogFunc(metroWindow))) as Task<TResult>;
}

private static MetroWindow GetMetroWindow(object context)
{
if (context == null) throw new ArgumentNullException("context");
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (!DialogParticipation.IsRegistered(context))
throw new InvalidOperationException(
"Context is not registered. Consider using DialogParticipation.Register in XAML to bind in the DataContext.");
{
throw new InvalidOperationException("Context is not registered. Consider using DialogParticipation.Register in XAML to bind in the DataContext.");
}

var association = DialogParticipation.GetAssociation(context);
var metroWindow = Window.GetWindow(association) as MetroWindow;

MetroWindow metroWindow;

if (Thread.CurrentThread.IsBackground)
{
metroWindow = association.Dispatcher.Invoke(new Func<Window>(() => Window.GetWindow(association))) as MetroWindow;
}
else
{
metroWindow = Window.GetWindow(association) as MetroWindow;
}

if (metroWindow == null)
{
throw new InvalidOperationException("Control is not inside a MetroWindow.");
}
return metroWindow;
}
}
}
}
21 changes: 17 additions & 4 deletions MahApps.Metro/Controls/Dialogs/DialogParticipation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@ public static class DialogParticipation
private static readonly IDictionary<object, DependencyObject> ContextRegistrationIndex = new Dictionary<object, DependencyObject>();

public static readonly DependencyProperty RegisterProperty = DependencyProperty.RegisterAttached(
"Register", typeof(object), typeof(DialogParticipation), new PropertyMetadata(default(object), RegisterPropertyChangedCallback));
"Register",
typeof(object),
typeof(DialogParticipation),
new PropertyMetadata(default(object), RegisterPropertyChangedCallback));

private static void RegisterPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
if (dependencyPropertyChangedEventArgs.OldValue != null)
{
ContextRegistrationIndex.Remove(dependencyPropertyChangedEventArgs.OldValue);
}

if (dependencyPropertyChangedEventArgs.NewValue != null)
{
ContextRegistrationIndex[dependencyPropertyChangedEventArgs.NewValue] = dependencyObject;
}
}

public static void SetRegister(DependencyObject element, object context)
Expand All @@ -32,16 +39,22 @@ public static object GetRegister(DependencyObject element)

internal static bool IsRegistered(object context)
{
if (context == null) throw new ArgumentNullException("context");
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}

return ContextRegistrationIndex.ContainsKey(context);
}

internal static DependencyObject GetAssociation(object context)
{
if (context == null) throw new ArgumentNullException("context");
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}

return ContextRegistrationIndex[context];
}
}
}
}
9 changes: 7 additions & 2 deletions samples/MetroDemo/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:exampleViews="clr-namespace:MetroDemo.ExampleViews"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="MahApps.Metro - Demo Application"
Width="960"
Height="600"
Expand Down Expand Up @@ -184,8 +185,12 @@
<MenuItem Click="ShowDialogOutside" Header="Show CustomDialog Externally" />
<Separator />
<MenuItem Command="{Binding ShowInputDialogCommand}" Header="Show InputDialog via VM" />
<MenuItem Command="{Binding ShowLoginDialogCommand}" Header="Show LoginDialog via VM" />
<MenuItem Command="{Binding ShowMessageDialogCommand}" Header="Show MessageDialog via VM" />
<MenuItem Command="{Binding ShowLoginDialogCommand}" Header="Show LoginDialog via VM ..." />
<MenuItem Header="Show MessageDialog via VM">
<MenuItem Command="{Binding ShowMessageDialogCommand}" CommandParameter="DISPATCHER_THREAD" Header="... from Main Thread" />
<MenuItem Command="{Binding ShowMessageDialogCommand}" CommandParameter="BACKGROUND_THREAD" Header="... from Background Thread" />
</MenuItem>

<MenuItem Command="{Binding ShowProgressDialogCommand}" Header="Show ProgressDialog via VM" />
<MenuItem Command="{Binding ShowCustomDialogCommand}" Header="Show CustomDialog via VM" />
</MenuItem>
Expand Down
29 changes: 24 additions & 5 deletions samples/MetroDemo/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,21 @@ public ICommand ShowMessageDialogCommand
return this.showMessageDialogCommand ?? (this.showMessageDialogCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = async x =>
{
await _dialogCoordinator.ShowMessageAsync(this, "Message from VM", "MVVM based messages!").ContinueWith(t => Console.WriteLine(t.Result));
}
ExecuteDelegate = x => PerformDialogCoordinatorAction(this.ShowMessage((string)x), (string)x == "DISPATCHER_THREAD")
});
}
}

private Action ShowMessage(string startingThread)
{
return () =>
{
var message = $"MVVM based messages!\n\nThis dialog was created by {startingThread} Thread with ID=\"{Thread.CurrentThread.ManagedThreadId}\"\n" +
$"The current DISPATCHER_THREAD Thread has the ID=\"{Application.Current.Dispatcher.Thread.ManagedThreadId}\"";
this._dialogCoordinator.ShowMessageAsync(this, $"Message from VM created by {startingThread}", message).ContinueWith(t => Console.WriteLine(t.Result));
};
}

private ICommand showProgressDialogCommand;

public ICommand ShowProgressDialogCommand
Expand All @@ -363,7 +370,19 @@ private async void RunProgressFromVm()

await controller.CloseAsync();
}


private static void PerformDialogCoordinatorAction(Action action, bool runInMainThread)
{
if (!runInMainThread)
{
Task.Factory.StartNew(action);
}
else
{
action();
}
}


private ICommand showCustomDialogCommand;

Expand Down