• [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的接口定义:

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

    ObjectPickerBase的定义:

    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,其代码如下:

        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代码如下:

    <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对象,代码如下:

    RegisterObjectPicker<Color, TestColorPickerViewModel, TestColorPickerPage>();
    

    其中RegisterObjectPicker方法的源码如下:

        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弹窗,最简单的调用方法时这样的:

            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弹出时的自定义配置项,例如:

            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链接点这里,欢迎大家使用,或者提出意见!

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

  • 相关阅读:
    Xcode工程文件打不开:cannot be opened because the project file cannot be parsed
    MAC系统压缩文件传到WINDOWS下出现乱码
    iOS-Xcode必备插件XAlign:瞬间优化你的代码
    那些不能错过的Xcode插件
    Xcode 5.0.1安装插件:规范注释生成器VVDocumenter + OSX 10.9.2
    由pushViewController说起可能出线的各种死法
    iPhone开发中从一个视图跳到另一个视图有三种方法:
    深入理解typedef
    通俗易懂地讲解 __block 变量
    Blocks Programming Topics
  • 原文地址:https://www.cnblogs.com/hhchaos/p/9961258.html
Copyright © 2020-2023  润新知