UWP開發入門(十一)——Attached Property的簡單應用


  UWP中的Attached Property即附加屬性,在實際開發中是很常見的,比如Grid.Row:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Button Grid.Row="1"></Button>
    </Grid>

   Grid.Row這個屬性並不是Button對象本身的實例方法,而是定義在Grid類型上的static property,實際使用時卻又附在其他控件的XAML里。

  我們今天不討論如何使用UWP中已經定義好的Attached Property(使用起來很簡單,沒啥好講的),也不會介紹附件屬性的定義,以及與.NET屬性的區別(MSDN文檔非常詳細),更不會花大力氣去分析附加屬性背后的原理(這個有大牛珠玉在前,不敢造次)。

  本篇僅以極簡單的例子來展示Attached Propery的應用場景,拋磚引玉以期共同學習提高。

  設想場景如下,需要根據文本內容,將電話號碼和郵箱地址以下划線藍色字體和普通文本區分開來:

  

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock local:RichTextBlockEx.RichText="種子我發你這個郵箱:SampleEmail@outlook.com,有事打我電話18610241024。"></TextBlock>
    </Grid>

  顯示文本UWP中一般是通過TextBlock來實現,一段文字中如果需要不同顏色,以及增加下划線就需要在TextBlockInlines屬性中添加不同的Inline的子類對象(比如RunUnderline等)。

  而修改TextBlockInlines集合需要直接操作TextBlock對象,UWP的程序又通常是MVVM結構,在ViewModel中不應添加對View層級的引用,這就要求不能在ViewModel中訪問TextBlock

  那么修改TextBlock的邏輯就只能放在View中,問題是最終返回的TextBlock需要根據運行時具體綁定的文本內容才能確定,要求同時能訪問TextBlock以及綁定的DataContext。似乎也不適合寫在Page.xaml.cs中。

  Attached Propery則非常完美的解決了我們的問題,首先附加屬性支持binding,這就將View中的TextBlockViewModel中的文本內容結合在一起;其次附加屬性是View層級的概念,通過它來修改TextBlock不會破壞MVVM的結構。

  接下來我們動手定義一個Attached Property

        public static string GetRichText(DependencyObject obj)
        {
            return (string)obj.GetValue(RichTextProperty);
        }

        public static void SetRichText(DependencyObject obj, string value)
        {
            obj.SetValue(RichTextProperty, value);
        }

        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RichTextProperty =
            DependencyProperty.RegisterAttached("RichText", typeof(string), typeof(RichTextBlockEx), new PropertyMetadata(null, RichTextChanged));

  這個附加屬性叫做RichTextProperty,我們給他做了GetRichTextSetRichText兩個方法的封裝,以便我們能像經典的.NET屬性一樣,通過“RichText”來訪問。具體的細節請參考MSDN的文檔,這里我們着重看一下RegisterAttached方法中傳遞了一個回調方法RichTextChanged

        private static void RichTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TextBlock textBlock = d as TextBlock;
            if (textBlock == null)
                return;
            string inputString = e.NewValue as string;
            if (string.IsNullOrEmpty(inputString) || string.IsNullOrWhiteSpace(inputString))
            {
                textBlock.Text = string.Empty;
                return;
            }
            textBlock.Inlines.Clear();
            CreateTextBlock(textBlock, inputString);
        }

  該方法是一個靜態方法,在biding的對象發生改變時觸發,並將biding的對象本身作為第一個參數傳遞進來。該方法的代碼先判斷了綁定的新值是否為空,不為空則調用CreateTextBlock方法,根據inputString來創建帶有藍色下划線的TextBlock

        private static void CreateTextBlock(TextBlock textBlock, string inputString)
        {
            var resultList = new List<MatchResult>();
            resultList.AddRange(GetMatchResultList(inputString));

            int offset = 0;
            var matchDicOrder = resultList.OrderBy(_ => _.Match.Index);
            foreach (var item in matchDicOrder)
            {
                var match = item.Match;
                if (match.Index >= offset)
                {
                    if (match.Index > 0 && match.Index != offset)
                    {
                        var text = inputString.Substring(offset, match.Index - offset);
                        AddText(textBlock, text);
                    }

                    var content = inputString.Substring(match.Index, match.Length);
                    AddUnderline(textBlock,  content);
                    offset = match.Index + match.Length;
                }
            }

            if (offset < inputString.Length)
            {
                var text = inputString.Substring(offset);
                AddText(textBlock, text);
            }
        }

  通過正則表達式匹配phoneemail,將匹配的內容通過AddUnderline方法添加到原TextBlock中,不匹配的內容則直接AddText

        private static void AddText(TextBlock textBlock, string text)
        {
            Run run = new Run();
            run.Text = text;
            textBlock.Inlines.Add(run);
        }

        private static void AddUnderline(TextBlock textBlock, string content)
        {
            Run run = new Run();
            run.Text = content;
            run.Foreground = new SolidColorBrush(Colors.Blue);
            Underline underline = new Underline();
            underline.Inlines.Add(run);

            textBlock.Inlines.Add(underline);
        }

  實際的開發中,這里可能存在更復雜的邏輯,比如即時通訊程序中存在@的概念,下划線的內容需要在點擊后做相應處理等(打電話,發郵件)。本篇中的代碼為了簡單清晰做了最簡化的處理,各位在自己的APP里可以進一步發揮想象補充,只要別讓手機或電腦爆炸就行……

  本篇有心回歸開發入門的初心,介紹的內容較為簡單,寫得不好還請包涵。

  照例放出GayHub地址:

  https://github.com/manupstairs/UWPSamples

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM