你的位置:首页 > ASP.net教程

[ASP.net教程]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来实现,一段文字中如果需要不同颜色,以及增加下划线就需要在TextBlock的Inlines属性中添加不同的Inline的子类对象(比如Run,Underline等)。

  而修改TextBlock的Inlines集合需要直接操作TextBlock对象,UWP的程序又通常是MVVM结构,在ViewModel中不应添加对View层级的引用,这就要求不能在ViewModel中访问TextBlock。

  那么修改TextBlock的逻辑就只能放在View中,问题是最终返回的TextBlock需要根据运行时具体绑定的文本内容才能确定,要求同时能访问TextBlock以及绑定的DataContext。似乎也不适合写在Page.xaml.cs中。

  Attached Propery则非常完美的解决了我们的问题,首先附加属性支持binding,这就将View中的TextBlock和ViewModel中的文本内容结合在一起;其次附加属性是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,我们给他做了GetRichText和SetRichText两个方法的封装,以便我们能像经典的.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);      }    }

  通过正则表达式匹配phone和email,将匹配的内容通过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