Merge pull request #58 from DingpingZhang/enhance-dialog

添加“Dialog.ShowAsync<T>(): T”函数以获得Dialog的返回值
This commit is contained in:
NaBian authored and GitHub committed 2019-04-03 22:08:22 +08:00
commit d26e29176d
13 files changed
+395 -161

No files matched your search

+16 -2
View File
@@ -1,4 +1,5 @@
using System.Windows.Controls;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using HandyControl.Interactivity;
@@ -10,11 +11,22 @@ namespace HandyControl.Controls
{
private Adorner _container;
public static readonly DependencyProperty IsClosedProperty = DependencyProperty.Register(
"IsClosed", typeof(bool), typeof(Dialog), new PropertyMetadata(default(bool)));
public bool IsClosed
{
get => (bool) GetValue(IsClosedProperty);
internal set => SetValue(IsClosedProperty, value);
}
public Dialog()
{
CommandBindings.Add(new CommandBinding(ControlCommands.Close, (s, e) => Close()));
}
public static Dialog Show<T>() where T : new() => Show(new T());
public static Dialog Show(object content)
{
var dialog = new Dialog
@@ -40,6 +52,7 @@ namespace HandyControl.Controls
Child = dialog
};
dialog._container = container;
dialog.IsClosed = false;
layer.Add(container);
}
}
@@ -62,8 +75,9 @@ namespace HandyControl.Controls
}
var layer = decorator.AdornerLayer;
layer?.Remove(_container);
IsClosed = true;
}
}
}
}
}
}
+1
View File
@@ -186,6 +186,7 @@
<Compile Include="Tools\Converter\BorderClipConverter.cs" />
<Compile Include="Tools\Converter\BorderCircularConverter.cs" />
<Compile Include="Tools\Converter\Int2StrConverter.cs" />
<Compile Include="Tools\Extension\DialogExtension.cs" />
<Compile Include="Tools\Extension\EnumerableExtension.cs" />
<Compile Include="Tools\Extension\GeometryExtension.cs" />
<Compile Include="Tools\GithubGravatarGenerator.cs" />
@@ -0,0 +1,78 @@
using System;
using System.Threading.Tasks;
using System.Windows;
using HandyControl.Controls;
namespace HandyControl.Tools.Extension
{
public interface IDialogResultable<T>
{
T Result { get; set; }
Action CloseAction { get; set; }
}
public static class DialogExtension
{
public static Task<TResult> GetResultAsync<TResult>(this Dialog dialog)
{
var tcs = new TaskCompletionSource<TResult>();
try
{
if (dialog.IsClosed)
{
SetResult();
}
else
{
dialog.Unloaded += OnUnloaded;
dialog.GetViewModel<IDialogResultable<TResult>>().CloseAction = dialog.Close;
}
}
catch (Exception e)
{
tcs.TrySetException(e);
}
return tcs.Task;
// ReSharper disable once ImplicitlyCapturedClosure
void OnUnloaded(object sender, RoutedEventArgs args)
{
dialog.Unloaded -= OnUnloaded;
SetResult();
}
void SetResult()
{
try
{
tcs.TrySetResult(dialog.GetViewModel<IDialogResultable<TResult>>().Result);
}
catch (Exception e)
{
tcs.TrySetException(e);
}
}
}
public static Dialog Initialize<TViewModel>(this Dialog dialog, Action<TViewModel> configure)
{
configure?.Invoke(dialog.GetViewModel<TViewModel>());
return dialog;
}
public static TViewModel GetViewModel<TViewModel>(this Dialog dialog)
{
if (!(dialog.Content is FrameworkElement frameworkElement))
throw new InvalidOperationException("The dialog is not a derived class of the FrameworkElement. ");
if (!(frameworkElement.DataContext is TViewModel viewModel))
throw new InvalidOperationException($"The view model of the dialog is not the {typeof(TViewModel)} type or its derived class. ");
return viewModel;
}
}
}
+8
View File
@@ -130,6 +130,9 @@
<Compile Include="UserControl\Basic\ChatBox.xaml.cs">
<DependentUpon>ChatBox.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Basic\InteractiveDialog.xaml.cs">
<DependentUpon>InteractiveDialog.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Basic\TextDialog.xaml.cs">
<DependentUpon>TextDialog.xaml</DependentUpon>
</Compile>
@@ -359,6 +362,7 @@
<DependentUpon>TreeViewDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="ViewModel\Basic\ChatBoxViewModel.cs" />
<Compile Include="ViewModel\Basic\InteractiveDialogViewModel.cs" />
<Compile Include="ViewModel\Common\ComboBoxDemoViewModel.cs" />
<Compile Include="ViewModel\Controls\CoverViewModel.cs" />
<Compile Include="ViewModel\Controls\DialogDemoViewModel.cs" />
@@ -455,6 +459,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Basic\InteractiveDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Basic\TextDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
File diff suppressed because it is too large. Load diff
@@ -552,4 +552,13 @@
<data name="Try2CloseApp" xml:space="preserve">
<value>Try to close app?</value>
</data>
<data name="InteractiveDialog" xml:space="preserve">
<value>Interactive Dialog</value>
</data>
<data name="Ok" xml:space="preserve">
<value>Ok</value>
</data>
<data name="PleaseInput" xml:space="preserve">
<value>Please input...</value>
</data>
</root>
@@ -552,4 +552,13 @@
<data name="Try2CloseApp" xml:space="preserve">
<value>试试关闭程序吧?</value>
</data>
<data name="InteractiveDialog" xml:space="preserve">
<value>可交互对话框</value>
</data>
<data name="Ok" xml:space="preserve">
<value>确定</value>
</data>
<data name="PleaseInput" xml:space="preserve">
<value>请输入...</value>
</data>
</root>
@@ -0,0 +1,16 @@
<Border x:Class="HandyControlDemo.UserControl.Basic.InteractiveDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:langs="clr-namespace:HandyControlDemo.Properties.Langs"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
CornerRadius="10"
Width="400"
Height="247"
DataContext="{Binding InteractiveDialog, Source={StaticResource Locator}}"
Background="{DynamicResource RegionBrush}">
<StackPanel VerticalAlignment="Center" Margin="32">
<TextBlock Style="{StaticResource TextBlockLargeBold}" Text="{Binding Message}"/>
<TextBox Margin="0,32,0,0" Style="{StaticResource TextBoxExtend}" Text="{Binding Result,UpdateSourceTrigger=PropertyChanged}" controls:InfoElement.Placeholder="{x:Static langs:Lang.PleaseInput}"/>
<Button Width="120" Margin="0,32,0,0" Command="{Binding CloseCmd}" Style="{StaticResource ButtonPrimary}" Content="{x:Static langs:Lang.Ok}"/>
</StackPanel>
</Border>
@@ -0,0 +1,10 @@
namespace HandyControlDemo.UserControl.Basic
{
public partial class InteractiveDialog
{
public InteractiveDialog()
{
InitializeComponent();
}
}
}
@@ -2,7 +2,15 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:langs="clr-namespace:HandyControlDemo.Properties.Langs"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
Background="{DynamicResource RegionBrush}"
MinWidth="300"
DataContext="{Binding DialogDemo,Source={StaticResource Locator}}">
<Button Margin="32" Content="{x:Static langs:Lang.TextDialog}" Command="{Binding ShowTextCmd}"/>
<controls:TransitioningContentControl>
<StackPanel Margin="32" VerticalAlignment="Center">
<Button Content="{x:Static langs:Lang.TextDialog}" Command="{Binding ShowTextCmd}" />
<TextBox Margin="0,32,0,0" Text="{Binding DialogResult,UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TextBoxExtend}" controls:InfoElement.Placeholder="{x:Static langs:Lang.PleaseInput}"/>
<Button Margin="0,10,0,0" Content="{x:Static langs:Lang.InteractiveDialog}" Command="{Binding ShowInteractiveDialogCmd}"/>
</StackPanel>
</controls:TransitioningContentControl>
</UserControl>
@@ -0,0 +1,30 @@
using System;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using HandyControl.Tools.Extension;
namespace HandyControlDemo.ViewModel.Basic
{
public class InteractiveDialogViewModel : ViewModelBase, IDialogResultable<string>
{
public Action CloseAction { get; set; }
private string _result;
public string Result
{
get => _result;
set => Set(ref _result, value);
}
private string _message;
public string Message
{
get => _message;
set => Set(ref _message, value);
}
public RelayCommand CloseCmd => new Lazy<RelayCommand>(() => new RelayCommand(() => CloseAction?.Invoke())).Value;
}
}
@@ -1,13 +1,25 @@
using System;
using System.Threading.Tasks;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using HandyControl.Controls;
using HandyControl.Tools.Extension;
using HandyControlDemo.UserControl;
using HandyControlDemo.UserControl.Basic;
using HandyControlDemo.ViewModel.Basic;
namespace HandyControlDemo.ViewModel
{
public class DialogDemoViewModel : ViewModelBase
{
private string _dialogResult;
public string DialogResult
{
get => _dialogResult;
set => Set(ref _dialogResult, value);
}
public RelayCommand ShowTextCmd => new Lazy<RelayCommand>(() =>
new RelayCommand(ShowText)).Value;
@@ -15,5 +27,15 @@ namespace HandyControlDemo.ViewModel
{
Dialog.Show(new TextDialog());
}
public RelayCommand ShowInteractiveDialogCmd => new Lazy<RelayCommand>(() =>
new RelayCommand(async () => await ShowInteractiveDialog())).Value;
private async Task ShowInteractiveDialog()
{
DialogResult = await Dialog.Show<InteractiveDialog>()
.Initialize<InteractiveDialogViewModel>(vm => vm.Message = DialogResult)
.GetResultAsync<string>();
}
}
}
@@ -1,10 +1,10 @@
using System;
using System.Reflection.Emit;
using System.Windows;
using CommonServiceLocator;
using GalaSoft.MvvmLight.Ioc;
using HandyControlDemo.Data;
using HandyControlDemo.Service;
using HandyControlDemo.ViewModel.Basic;
namespace HandyControlDemo.ViewModel
{
@@ -30,6 +30,7 @@ namespace HandyControlDemo.ViewModel
SimpleIoc.Default.Register<DialogDemoViewModel>();
SimpleIoc.Default.Register<SearchBarDemoViewModel>();
SimpleIoc.Default.Register<NotifyIconDemoViewModel>();
SimpleIoc.Default.Register<InteractiveDialogViewModel>();
}
public static ViewModelLocator Instance => new Lazy<ViewModelLocator>(() =>
@@ -65,6 +66,7 @@ namespace HandyControlDemo.ViewModel
public NotifyIconDemoViewModel NotifyIconDemo => ServiceLocator.Current.GetInstance<NotifyIconDemoViewModel>();
public InteractiveDialogViewModel InteractiveDialog => ServiceLocator.Current.GetInstance<InteractiveDialogViewModel>();
#endregion
}
}