Skip to content

Commit

Permalink
initial attempt at a new dialog service
Browse files Browse the repository at this point in the history
  • Loading branch information
brianlagunas committed Jan 17, 2019
1 parent 7baeb32 commit 457c725
Show file tree
Hide file tree
Showing 16 changed files with 354 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
using Prism.Mvvm;
using System;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services.Dialogs;

namespace HelloWorld.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Application";
private readonly IDialogService _dialogService;

public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}

public MainWindowViewModel()
public DelegateCommand ShowDialogCommand { get; private set; }

public MainWindowViewModel(IDialogService dialogService)
{
ShowDialogCommand = new DelegateCommand(ShowDialog);
_dialogService = dialogService;
}

private void ShowDialog()
{
_dialogService.ShowNotification("This is a title", "This is a message!", r => Title = "CallBack");
}
}
}
4 changes: 3 additions & 1 deletion Sandbox/Wpf/HelloWorld/HelloWorld/Views/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525">

<Grid>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
<Button Command="{Binding ShowDialogCommand}" Content="Show Dialog" />
<!--<ContentControl prism:RegionManager.RegionName="ContentRegion" />-->
</Grid>
</Window>
2 changes: 2 additions & 0 deletions Source/Wpf/Prism.Wpf/PrismApplicationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Prism.Mvvm;
using Prism.Regions;
using Prism.Regions.Behaviors;
using Prism.Services.Dialogs;
using System;
using System.Linq;
using System.Windows;
Expand Down Expand Up @@ -117,6 +118,7 @@ protected virtual void RegisterRequiredTypes(IContainerRegistry containerRegistr
containerRegistry.RegisterInstance(_containerExtension);
containerRegistry.RegisterInstance(_moduleCatalog);
containerRegistry.RegisterSingleton<ILoggerFacade, TextLogger>();
containerRegistry.RegisterSingleton<IDialogService, DialogService>();
containerRegistry.RegisterSingleton<IModuleInitializer, ModuleInitializer>();
containerRegistry.RegisterSingleton<IModuleManager, ModuleManager>();
containerRegistry.RegisterSingleton<RegionAdapterMappings>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Window x:Class="Prism.Services.Dialogs.DefaultDialogs.DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding Title}" Icon="{Binding IconSource}"
WindowStartupLocation="CenterOwner" MinWidth="300" MinHeight="150">
<Window.Style>
<Style TargetType="{x:Type Window}" >
<Setter Property="SizeToContent" Value="WidthAndHeight" />
</Style>
</Window.Style>
</Window>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Windows;

namespace Prism.Services.Dialogs.DefaultDialogs
{
/// <summary>
/// Interaction logic for DialogWindow.xaml
/// </summary>
public partial class DialogWindow : Window, IDialogWindow
{
public IDialog ViewModel
{
get { return (IDialog)DataContext; }
set { DataContext = value; }
}

public DialogWindow()
{
InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<UserControl x:Class="Prism.Services.Dialogs.DefaultDialogs.NotificationDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:mvvm="clr-namespace:Prism.Mvvm"
mvvm:ViewModelLocator.AutoWireViewModel="True"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot" Margin="5">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<TextBlock Text="{Binding Message}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" />
<Button Command="{Binding CloseDialogCommand}" Content="OK" Width="75" Height="25" HorizontalAlignment="Right" Margin="0,10,0,0" Grid.Row="1" IsDefault="True" />
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Windows.Controls;

namespace Prism.Services.Dialogs.DefaultDialogs
{
/// <summary>
/// Interaction logic for NotificationDialog.xaml
/// </summary>
public partial class NotificationDialog : UserControl
{
public NotificationDialog()
{
InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Prism.Commands;
using Prism.Mvvm;
using System;

namespace Prism.Services.Dialogs.DefaultDialogs
{
public class NotificationDialogViewModel : BindableBase, IDialog
{
private string _title;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}

public event Action RequestClose;

private string _message;
public string Message
{
get { return _message; }
set { SetProperty(ref _message, value); }
}

public DelegateCommand CloseDialogCommand { get; set; }

private string _iconSource;
public string IconSource
{
get { return _iconSource; }
set { SetProperty(ref _iconSource, value); }
}

public NotificationDialogViewModel()
{
CloseDialogCommand = new DelegateCommand(CloseDialog);
}

private void CloseDialog()
{
RequestClose?.Invoke();
}

public bool CanCloseDialog()
{
return true;
}

public void ProcessDialogParameters(IDialogParameters parameters)
{
Title = parameters.GetValue<string>("title");
Message = parameters.GetValue<string>("message");
}
}
}
12 changes: 12 additions & 0 deletions Source/Wpf/Prism.Wpf/Services/Dialogs/DialogParameters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Prism.Regions;

namespace Prism.Services.Dialogs
{
//TODO: should we reuse the NavigatrionParameters? I'm not sure I want to add the regions namespace requirement for using dialogs
public class DialogParameters : NavigationParameters, IDialogParameters
{
public DialogParameters(string query) : base(query)
{
}
}
}
7 changes: 7 additions & 0 deletions Source/Wpf/Prism.Wpf/Services/Dialogs/DialogResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Prism.Services.Dialogs
{
public class DialogResult : IDialogResult
{

}
}
107 changes: 107 additions & 0 deletions Source/Wpf/Prism.Wpf/Services/Dialogs/DialogService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using Prism.Common;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Services.Dialogs.DefaultDialogs;
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;

namespace Prism.Services.Dialogs
{
public class DialogService : IDialogService
{
private readonly IContainerExtension _containerExtension;

public DialogService(IContainerExtension containerExtension)
{
_containerExtension = containerExtension;

RegisterDialog<NotificationDialog, NotificationDialogViewModel>();
}

public void ShowNotification(string title, string message, Action<IDialogResult> callback)
{
var parameters = new DialogParameters($"?title={title}&message={message}");

IDialogWindow dialogWindow = CreateDialogWindow();
ConfigureDialogWindowEvents(dialogWindow, callback);
ConfigureDialogWindowContent<NotificationDialog>(dialogWindow, parameters);

//TODO: figure out how to control the parent (is this even neccessary? Should we assume the parent should be the active window?
dialogWindow.Owner = Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive);
//TODO: figure out how to control various properties of the window, maybe a WindowSettings object?
//TODO: handle modal/non-modal dialogs
dialogWindow.ShowDialog();
}

//TODO: create extension point to provide a custom Window
IDialogWindow CreateDialogWindow()
{
return new DialogWindow();
}

void ConfigureDialogWindowContent<T>(IDialogWindow window, IDialogParameters parameters)
{
var content = _containerExtension.Resolve<T>();
var dialogContent = content as FrameworkElement;
if (dialogContent == null)
throw new NullReferenceException("A dialog's content must be a FrameworkElement");

var viewModel = dialogContent.DataContext as IDialog;
if (viewModel == null)
throw new NullReferenceException("A dialog's ViewModel must implement the IDialog interface");

MvvmHelpers.ViewAndViewModelAction<IDialog>(viewModel, d => d.ProcessDialogParameters(parameters));

window.Content = dialogContent;
window.ViewModel = viewModel;
}

void ConfigureDialogWindowEvents(IDialogWindow dialogWindow, Action<IDialogResult> callback)
{
Action requestCloseHandler = null;
requestCloseHandler = () =>
{
dialogWindow.Close();
};

RoutedEventHandler loadedHandler = null;
loadedHandler = (o, e) =>
{
dialogWindow.Loaded -= loadedHandler;
dialogWindow.ViewModel.RequestClose += requestCloseHandler;
};
dialogWindow.Loaded += loadedHandler;

CancelEventHandler closingHandler = null;
closingHandler = (o, e) =>
{
if (!dialogWindow.ViewModel.CanCloseDialog())
e.Cancel = true;
};
dialogWindow.Closing += closingHandler;

EventHandler closedHandler = null;
closedHandler = (o, e) =>
{
dialogWindow.Closed -= closedHandler;
dialogWindow.Closing -= closingHandler;
dialogWindow.ViewModel.RequestClose -= requestCloseHandler;
//TODO: get dialog result from ViewModel
callback?.Invoke(new DialogResult());
dialogWindow.ViewModel = null;
dialogWindow.Content = null;
};
dialogWindow.Closed += closedHandler;
}

public void RegisterDialog<TView, TViewModel>() where TViewModel : IDialog
{
_containerExtension.Register<TView>();
ViewModelLocationProvider.Register<TView, TViewModel>();
}
}
}
17 changes: 17 additions & 0 deletions Source/Wpf/Prism.Wpf/Services/Dialogs/IDialog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;

namespace Prism.Services.Dialogs
{
public interface IDialog
{
bool CanCloseDialog();

string IconSource { get; set; }

string Title { get; set; }

event Action RequestClose;

void ProcessDialogParameters(IDialogParameters parameters);
}
}
21 changes: 21 additions & 0 deletions Source/Wpf/Prism.Wpf/Services/Dialogs/IDialogParameters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Collections.Generic;

namespace Prism.Services.Dialogs
{
public interface IDialogParameters
{
void Add(string key, object value);

bool ContainsKey(string key);

int Count { get; }

IEnumerable<string> Keys { get; }

T GetValue<T>(string key);

IEnumerable<T> GetValues<T>(string key);

bool TryGetValue<T>(string key, out T value);
}
}
7 changes: 7 additions & 0 deletions Source/Wpf/Prism.Wpf/Services/Dialogs/IDialogResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Prism.Services.Dialogs
{
public interface IDialogResult
{
//TODO: what should we return?
}
}
17 changes: 17 additions & 0 deletions Source/Wpf/Prism.Wpf/Services/Dialogs/IDialogService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;

namespace Prism.Services.Dialogs
{
public interface IDialogService
{
void ShowNotification(string title, string message, Action<IDialogResult> callback);

//ShowConfirmation

//ShowDialog - this is for custom dialogs

//RegisterDialog

//RegisterDialogWindow
}
}
Loading

0 comments on commit 457c725

Please sign in to comment.