Skip to content

Instantly share code, notes, and snippets.

@tianvan
Last active September 12, 2024 06:50
Show Gist options
  • Save tianvan/7c9422293ae52f72a682858101598277 to your computer and use it in GitHub Desktop.
Save tianvan/7c9422293ae52f72a682858101598277 to your computer and use it in GitHub Desktop.
Prism combine with Material Design Toolkit Dialog
namespace Core.Services.Dialog
{
public class DialogHostRegionAdapter : RegionAdapterBase<DialogHost>
{
public DialogHostRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) : base(regionBehaviorFactory)
{
}
protected override void Adapt(IRegion region, DialogHost regionTarget)
{
if (regionTarget == null)
{
throw new ArgumentNullException("regionTarget");
}
if (regionTarget.Content != null || BindingOperations.GetBinding(regionTarget, DialogHost.DialogContentProperty) != null)
{
throw new InvalidOperationException("DialogContent can not be set");
}
region.ActiveViews.CollectionChanged += (sender, e) => regionTarget.DialogContent = region.ActiveViews.FirstOrDefault();
region.Views.CollectionChanged += delegate (object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add && !region.ActiveViews.Any())
{
region.Activate(e.NewItems[0]);
}
};
}
protected override IRegion CreateRegion() => new SingleActiveRegion();
}
}
namespace Core.Services.Dialog
{
public class DialogService : IDialogService
{
private readonly IUnityContainer _container;
private readonly IRegionManager _regionManager;
public DialogService(IUnityContainer container, IRegionManager regionManager)
{
_container = container;
_regionManager = regionManager;
}
public void Show(string name, dynamic parameters, System.Action<dynamic> callback)
{
IRegion region = _regionManager.Regions["DialogRegion"];
var view = _container.Resolve(typeof(object), name);
if (!(view is UIElement))
{
throw new ArgumentException("A dialog must be a UIElement");
}
var dialog = view as FrameworkElement;
if (!(dialog.DataContext is IDialogAware))
{
throw new ArgumentException("A dialog's ViewModel must implement IDialogAware interface");
}
var viewModel = dialog.DataContext as IDialogAware;
DialogHost dialogHost = FindChild<DialogHost>(Application.Current.MainWindow, default);
ConfigureEvents(dialogHost, viewModel, callback);
MvvmHelpers.ViewAndViewModelAction<IDialogAware>(viewModel, d => d.OnDialogOpened(parameters));
_ = region.Add(dialog);
region.Activate(dialog);
dialogHost.IsOpen = true;
}
private void ConfigureEvents(DialogHost dialogHost, IDialogAware viewModel, Action<dynamic> callback)
{
dynamic temp = default;
dialogHost.DialogOpened += DialogOpenedHandler;
dialogHost.DialogClosing += DialogClosedHandler;
void DialogOpenedHandler(object sender, RoutedEventArgs e)
{
dialogHost.DialogOpened -= DialogOpenedHandler;
viewModel.RequestClose += RequestCloseHandler;
}
void RequestCloseHandler(dynamic result)
{
temp = result;
dialogHost.IsOpen = false;
}
void DialogClosedHandler(object sender, RoutedEventArgs e)
{
dialogHost.DialogClosing -= DialogClosedHandler;
viewModel.RequestClose -= RequestCloseHandler;
viewModel.OnDialogClosed();
_ = callback?.Invoke(temp);
}
}
public void ShowDialog(string name, dynamic parameters, System.Action<dynamic> callback) => throw new System.NotImplementedException();
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
if (parent == null)
{
return default;
}
T foundChild = default;
var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (!(child is T))
{
foundChild = FindChild<T>(child, childName);
if (foundChild != null)
{
break;
}
}
else if (!string.IsNullOrEmpty(childName))
{
if (child is FrameworkElement frameworkElement && frameworkElement.Name == childName)
{
foundChild = (T)child;
break;
}
}
else
{
foundChild = (T)child;
break;
}
}
return foundChild;
}
}
}
<UserControl x:Class="Dialogs.ExitApplicationDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:properties="clr-namespace:Properties"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Themes/Button.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Border CornerRadius="8"
Background="White">
<StackPanel>
<StackPanel Margin="24,16,24,28">
<TextBlock Text="{x:Static properties:Resources.ExitApplicationDialogHeader}"
Style="{DynamicResource MaterialDesignHeadlineTextBlock}" />
<TextBlock Margin="0,23,0,0"
Style="{DynamicResource MaterialDesignBody1TextBlock}"
Text="{x:Static properties:Resources.ExitApplicationDialogBody}"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="8">
<Button Content="{x:Static properties:Resources.Cancel}"
Margin="0,0,8,0"
Style="{DynamicResource MaterialDesignFlatButton}"
Command="{Binding CancelCommand}" />
<Button Content="{x:Static properties:Resources.Confirm}"
Style="{DynamicResource MaterialDesignFlatButton}"
Command="{Binding ConfirmCommand}" />
</StackPanel>
</StackPanel>
</Border>
</UserControl>
namespace Dialogs
{
/// <summary>
/// Interaction logic for ExitDialog.xaml
/// </summary>
public partial class ExitApplicationDialog : UserControl
{
public ExitApplicationDialog(ExitApplicationDialogViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
}
namespace Dialogs
{
public class ExitApplicationDialogViewModel : IDialogAware
{
private readonly IWorkspaceManger _workspaceManger;
private readonly ISnackbarMessageQueue _snackbarMessageQueue;
private MetroWindow _metroWindow;
public ExitApplicationDialogViewModel(IWorkspaceManger workspaceManger, ISnackbarMessageQueue snackbarMessageQueue)
{
_workspaceManger = workspaceManger;
_snackbarMessageQueue = snackbarMessageQueue;
}
public event Action<dynamic> RequestClose;
public void OnDialogClosed()
{
// Method intentionally left empty.
}
public void OnDialogOpened(dynamic parameters)
{
_metroWindow = Application.Current.MainWindow as MetroWindow;
_metroWindow.IsCloseButtonEnabled = false;
}
private DelegateCommand _cancelCommand;
public DelegateCommand CancelCommand =>
_cancelCommand ?? (_cancelCommand = new DelegateCommand(ExecuteCancelCommand));
private void ExecuteCancelCommand()
{
RequestClose?.Invoke(default);
_metroWindow.IsCloseButtonEnabled = true;
}
private DelegateCommand _confirmCommand;
public DelegateCommand ConfirmCommand =>
_confirmCommand ?? (_confirmCommand = new DelegateCommand(ExecuteConfirmCommand));
private void ExecuteConfirmCommand()
{
foreach (IntegratedControl item in Application.Current.MainWindow.FindChildren<IntegratedControl>())
{
item.Save();
}
RequestClose?.Invoke(default);
Application.Current.Shutdown(0);
}
}
}
namespace Core.Services.Dialog
{
public interface IDialogAware
{
void OnDialogClosed();
void OnDialogOpened(dynamic parameters);
event Action<dynamic> RequestClose;
}
}
namespace Core.Services.Dialog
{
public interface IDialogService
{
void Show(string name, dynamic parameters, Action<dynamic> callback);
void ShowDialog(string name, dynamic parameters, Action<dynamic> callback);
}
}
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
<materialDesign:DialogHost prism:RegionManager.RegionName="DialogRegion" />
@AcidRaZor
Copy link

How do you call the dialog once all classes have been created and regionAdapter has been registered? RequestNavigate does nothing

@tianvan
Copy link
Author

tianvan commented Oct 8, 2020

How do you call the dialog once all classes have been created and regionAdapter has been registered? RequestNavigate does nothing

_dialogService.Show(nameof(ExitApplicationDialog));

@Honey-Fist
Copy link

what is MvvmHelpers?

@elusive
Copy link

elusive commented Sep 28, 2021

what is MvvmHelpers?

builtin helper class in Prism

@Andy1666
Copy link

Hey, i createt a PopupDialogServive using the IDialogAware from prism.

https://gist.github.com/Andy1666/03a5ccb98603aa7241e04f976382050b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment