[UWP]使用Picker实现一个简单的ColorPicker弹窗

在上一篇博文《[UWP]使用Popup构建UWP Picker》中我们简单讲述了一下使用Popup构建适用于MVVM框架下的弹窗层组件Picker的过程。但是没有应用实例的话可能体现不出Picker相对于ContentDialog的优点在哪里,毕竟Linus大神说过:

Talk is cheap, show me the code!

我们假定要实现这样一个颜色选择器:当用户需要选择一个颜色时,应用弹出颜色选择器,用户选择完成后,点击“确定”按钮关闭弹窗,并且向调用方代码返回用户选择的颜色值。

它的调用界面是这样的:

ColorPicker

编写ColorPicker弹窗的业务逻辑代码#

上篇博文里我们讲到要实现Picker功能,其ViewModel必须实现IObjectPicker接口。我在HHChaosToolkit库中已经定义了ObjectPickerBase作为Picker的公共基类,我们的ViewModel直接继承它就可以了。

IObjectPicker的接口定义:

Copy
public interface IObjectPicker<T> { event EventHandler<ObjectPickedEventArgs<T>> ObjectPicked; event EventHandler Canceled; }

ObjectPickerBase的定义:

Copy
public abstract class ObjectPickerBase<T> : ViewModelBase, IObjectPicker<T> { public event EventHandler<ObjectPickedEventArgs<T>> ObjectPicked; public event EventHandler Canceled; /// <summary> /// 设置选择的对象 /// </summary> /// <param name="result"></param> public void SetResult(T result) { ObjectPicked?.Invoke(this, new ObjectPickedEventArgs<T>(result)); } /// <summary> /// 取消Pick操作 /// </summary> public void Exit() { Canceled?.Invoke(this, EventArgs.Empty); } public RelayCommand ExitCommand => new RelayCommand(Exit); }

这里我们编写一个TestColorPickerViewModel作为ColorPicker弹窗界面的ViewModel,其代码如下:

Copy
public class TestColorPickerViewModel: ObjectPickerBase<Color> { private Color _pickedColor; public Color PickedColor { get => _pickedColor; set => Set(ref _pickedColor, value); } public override void OnNavigatedTo(NavigationEventArgs e) { if (e.Parameter is Color color) { PickedColor = color; } base.OnNavigatedTo(e); } public ICommand PickColorCommand => new RelayCommand(() => { SetResult(PickedColor); }); }

其中有一个重载的方法OnNavigatedTo,这个用于接受打开弹窗时给传递给Picker的参数,这个属于HHChaosToolkit类库中MVVM导航服务的一部分功能,以后的博客我可能会拿出来单独讲一下。

我们看到,TestColorPickerViewModel的代码逻辑非常简单,在执行PickColorCommand后返回PickedColor作为结果。

编写ColorPicker的UI层代码#

View层交互不多,我们新建一个Page,然后添加一个ColorPicker控件,Color属性绑定ViewModel的PickedColor,添加一个“确定”按钮绑定PickColorCommand,xaml.cs文件中无需添加任何代码,xaml代码如下:

Copy
<Page x:Class="HHChaosToolkit.Sample.Views.TestPages.TestColorPickerPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:HHChaosToolkit.Sample.Views.TestPages" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" DataContext="{Binding TestColorPickerViewModel, Source={StaticResource Locator}}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid> <Grid Background="White" BorderBrush="#d9ddea" BorderThickness="1"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid Height="40" Background="#d9ddea"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <TextBlock Margin="15,0" VerticalAlignment="Center" FontSize="14px" Foreground="#474261" Text="ColorPicker" /> <Button Grid.Column="1" Command="{Binding ExitCommand}" Style="{StaticResource PickerCloseButtonStyle}" /> </Grid> <Grid Grid.Row="1" Padding="20,10"> <ColorPicker x:Name="ColorPicker" Color="{Binding PickedColor,Mode=TwoWay}"/> </Grid> <Grid Grid.Row="2" Padding="20"> <Button HorizontalAlignment="Center" Content="确定" Command="{Binding PickColorCommand}"/> </Grid> </Grid> </Grid> </Page>

注册调用过程#

注册ColorPicker弹窗#

我们首先要在ViewModelLocator中注册TestColorPickerViewModel为可选取Color类型的Picker对象,代码如下:

Copy
RegisterObjectPicker<Color, TestColorPickerViewModel, TestColorPickerPage>();

其中RegisterObjectPicker方法的源码如下:

Copy
public void RegisterObjectPicker<T, VM, V>() where VM : ObjectPickerBase<T> { SimpleIoc.Default.Register<VM>(); ObjectPickerService.Configure(typeof(T).FullName, typeof(VM).FullName, typeof(V)); }

这段代码目的是在ObjectPickerService中注册TestColorPickerViewModel为可选取Color类型的Picker对象,这样我们之后的调用可以直接通过ObjectPickerService来进行。

必须要说明的是ObjectPickerService可以为同一类型注册多个Picker对象,类似于Windows系统中可安装多个视频播放器,调用时指定使用哪个播放器即可。

调用ColorPicker弹窗#

在ObjectPickerService中注册过后,我们即可在任意需要选取颜色的地方使用我们的ColorPicker弹窗,最简单的调用方法时这样的:

Copy
var pickerService = ServiceLocator.Current.GetInstance<ObjectPickerService>(); var ret = await pickerService.PickSingleObjectAsync<Color>(typeof(TestColorPickerViewModel) .FullName, PickedColor); if (!ret.Canceled) { PickedColor = ret.Result; var toast = new Toast($"You picked a new color!({ret.Result})"); toast.Show(); }

当然我们也可以自定义弹出界面的位置、背景、动画及点击空白区域退出等选项。如果需要这样自定义的话,我们要用到PickerOpenOption这个类,这个类用来设置Picker弹出时的自定义配置项,例如:

Copy
var pickerService = ServiceLocator.Current.GetInstance<ObjectPickerService>(); var openOption = new PickerOpenOption { EnableTapBlackAreaExit = true, VerticalAlignment = VerticalAlignment.Stretch, HorizontalAlignment = HorizontalAlignment.Right, Background = new AcrylicBrush { TintOpacity = 0.1 }, Transitions = new TransitionCollection { new EdgeUIThemeTransition { Edge = EdgeTransitionLocation.Right } } }; var ret = await pickerService.PickSingleObjectAsync<Color>(typeof(TestColorPickerViewModel) .FullName, PickedColor, openOption); if (!ret.Canceled) { PickedColor = ret.Result; var toast = new Toast($"You picked a new color!({ret.Result})"); toast.Show(); }

它的呈现效果是这样的:

ColorPicker

结尾#

这篇博文里我给大家讲解了如何使用Picker来构建一个颜色选择器弹窗,这只是一个小例子,Picker有非常多的使用场景,例如:

  • 文本输入弹窗(注册类型为string);
  • 普通自定义Dialog界面(统一注册类型为bool即可);
  • 图片编辑弹窗(注册类型为文件或者图片);
  • ...

最后,完整项目代码链接在这里:GitHub链接点这里,欢迎大家使用,或者提出意见!

本篇博客到此结束!谢谢大家!

posted @   HHChaos  阅读(1049)  评论(0编辑  收藏  举报
编辑推荐:
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
阅读排行:
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· PPT革命!DeepSeek+Kimi=N小时工作5分钟完成?
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· DeepSeek企业级部署实战指南:从服务器选型到Dify私有化落地
· 程序员转型AI:行业分析
点击右上角即可分享
微信分享提示
CONTENTS