[UWP]使用Picker實現一個簡單的ColorPicker彈窗

来源:https://www.cnblogs.com/hhchaos/archive/2018/11/15/9961258.html
-Advertisement-
Play Games

在上一篇博文《 "[UWP]使用Popup構建UWP Picker" 》中我們簡單講述了一下使用Popup構建適用於MVVM框架下的彈窗層組件Picker的過程。但是沒有應用實例的話可能體現不出Picker相對於ContentDialog的優點在哪裡,畢竟Linus大神說過: Talk is che ...


在上一篇博文《[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鏈接點這裡,歡迎大家使用,或者提出意見!

本篇博客到此結束!謝謝大家!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • .NET ThreadPool 最大線程數的限制 IIS併發瓶頸,有幾個地方,IIS線程池的最大隊列數,工作進程數,最大併發數。這些這裡就不展開。主要是最近因為過度使用Task 導致的線程數占用過多,所以實驗了一下 .net線程池 的限制,分享一下。 註意IIS線程池與.NET線程池不是同一個東西, ...
  • 問題:伺服器未提供有意義的回覆;這可能是由協定不匹配、會話過早關閉或內部伺服器錯誤引起的。 另類的解決辦法,如果實在沒有思路,不妨把代碼還原一下,然後把更改的內容在重新添加一遍,或許問題就解決了。 ...
  • 背景        最近需要將一些外部的 及其他 介面的調用移到一個獨立的 項目中,然後供其他 項目調用。之前的幾個 已經成功遷移,但是在遷移一個需要用戶名密碼認證的 介面的時候卻始終調用不成功。下麵直接上代碼。 示例代碼 在 中 ...
  • 很多時候我們做網站時單純的用bootstrap等前端框架實現的前端自適應帶給用戶的體驗並不太好,所以為了提高用戶體驗會專門針對PC端網頁重新設計一套移動端網頁,但是怎麼才能做到在移動端訪問PC頁面的時候返回對應的移動端頁面,而不是PC端頁面呢?下麵我們就簡單的進行介紹。主要技術是asp.net co ...
  • 在開發查看流程表單明細的時候,在Web界面中,我們往往通過使用@RenderPage實現頁面內容模塊化的隔離,減少複雜度,因此把一些常用的如審批、撤銷、會簽、閱辦等等的流程步驟都放到了通用處理的頁面ViewDetail.cshtml裡面實現了。那麼如果在一些特殊的表單處理過程中,我們在審批完成後需要... ...
  • 背景 在與後臺API介面對接時,如將網頁Url作為參數請求數據時,如果是錨點參數,則會丟失。 錨點參數 請求通過WebRequest.Create創建一個WebRequest: 得到的webRequest,發現後面的錨點參數沒有了。如下圖: 獲取的webRequest,Address和Request ...
  • 實現的功能以及效果如下: 樣式代碼: .divtable { display: table; border-collapse: collapse; border-spacing: 0; margin-right: auto; margin-left: auto; width: 100%; } .di ...
  • win10更新後出現System.ComponentModel.Win32Exception 我的環境是由於“sql server2012 無法連接到WMI提供程式”引起的 參考http://www.cnblogs.com/shixinchao/p/4230347.html解決的 命令語句:C:\U ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...