【WPF标记扩展 】开篇 标记扩展

原文

阅读此文之前必备知识

类型转换器

内容属性

XAML标记扩展定义

 

WPF 标记扩展 有哪些

WPF 编程中最常用的标记扩展是支持资源引用的标记扩展(StaticResource 和 DynamicResource)以及支持数据绑定的标记扩展 (Binding)。

多个 XAML 标记扩展是 XAML 2009 规范的一部分。 这些内容显示在具有自定义 x 命名空间前缀的 XAML 文件中,通常使用此前缀。 

本文讨论以下标记扩展:

  • x:Static – 引用静态属性、字段或枚举成员。
  • x:Reference – 引用页面上的命名元素。
  • x:Type – 将属性设置为 System.Type 对象。
  • x:Array – 构造特定类型的对象的数组。
  • x:Null – 将属性设置为值 null
  • OnPlatform – 基于每个平台自定义 UI 外观。
  • OnIdiom – 根据运行应用程序的设备的语态自定义 UI 外观。
  • DataTemplate – 将类型转换为 DataTemplate.
  • FontImage – 在任何可显示字体的视图中显示 ImageSource字体图标。
  • AppThemeBinding – 使用基于当前系统主题的资源。

其他 XAML 标记扩展历来受其他 XAML 实现的支持,也受 Xamarin.Forms支持。 其他文章更全面地介绍了这些内容:

  • StaticResource - 引用资源字典中的对象,如 “资源字典”一文中所述。
  • DynamicResource - 响应资源字典中对象的更改,如 “动态样式”一文中所述。
  • Binding - 根据 数据绑定一文中所述,在两个对象的属性之间建立链接。
  • TemplateBinding - 从控件模板执行数据绑定,如文章 Xamarin.Forms 控件模板中所述。
  • RelativeSource - 设置绑定源相对于绑定目标的位置,如文章 相对绑定中所述。

布局 RelativeLayout 使用自定义标记扩展 ConstraintExpression。 此标记扩展在 RelativeLayout 一文中介绍。

语法规则

语法一、当用于提供特性值时,将标记扩展序列与 XAML 处理器区分开的语法是左右大括号({ 和 })。 然后,由紧跟在左大括号后面的字符串标记来标识标记扩展的类型。

  <Button Content = "{local:MyMarkupExtension FirstStr = Markup, SecondStr = Extension}" Width = "200" Height = "20" /> 

 

语法二、当用在属性元素语法中时,标记扩展在外观上与任何其他用于提供属性元素值的元素相同,即:一个将标记扩展类作为元素引用并以尖括号 (<>) 括起的 XAML 元素声明。

  <TextBlock  >
       <TextBlock.Text>
             <local:MyMarkupExtension FirstStr="MyMarkup1" SecondStr="Extension2"></local:MyMarkupExtension>
        </TextBlock.Text>
 </TextBlock>

 语法三、缩写 、省略 Extension

  <Button Content = "{local:MyMarkup  FirstStr = Markup, SecondStr = Extension}" Width = "200" Height = "20" /> 

  语法三、 省略 内容属性

 

<Label Text="{Binding Source={x:Reference Name=page}
//Name 是内容属性 所以可以简写成
<Label Text="{Binding Source={x:Reference page}

 

代码

 

[ContentProperty("Name")]//Name 是内容属性
    public class Reference : MarkupExtension
    {
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        public Reference();
        public Reference(string name);
 
        [ConstructorArgument("name")]
        public string Name { get; set; }
 
        public override object ProvideValue(IServiceProvider serviceProvider);
    }

 内容属性需要类型转换器,而内容属性的含义就是在 Xaml 中,哪个属性可以直接表示该元素的内容。

 

<Button Content="Click Me!"/>

<Button>
    <Button.Content>
        Click Me!
    </Button.Content>
</Button>

<Button>
    Click Me! 这就是内容转换器的功能
</Button>

 

 

用途

标记扩展基类

WPF

若要定义可与 System.Xaml 中的 XAML 读取器和 XAML 编写器的默认实现进行交互的自定义标记扩展,请从抽象的 MarkupExtension 类派生一个类。该类有一个要重写的方法,即 ProvideValue。您可能还需要定义其他构造函数来支持标记扩展用法的参数,并匹配可设置的属性。

Xamarin.Forms

IMarkupExtension 接口或IMarkupExtension<T>接口,IMarkupExtension两个接口只定义一个方法,分别命名ProvideValue

public interface IMarkupExtension
{
    object ProvideValue(IServiceProvider serviceProvider);
}

public interface IMarkupExtension<out T> : IMarkupExtension
{
    new T ProvideValue(IServiceProvider serviceProvider);
}

 

自定义标记扩展

在上述XAML代码中,创建一个带有某些属性的按钮,对于内容值,自定义标记扩展名(My:MyMarkupExtension)已被分别用于分配给FirstStr和SecondStr的两个值“Markup”和“Extension”。

其实,MyMarkupExtension是一个派生自MarkupExtensionC#实现中的下面的类。此类包含两个字符string变量FirstStr和SecondStr,它们连接并将该字符string从ProvideValue方法返回到按钮的内容。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;
 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Markup; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes;  

namespace XAMLMarkupExtension { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
    
   public partial class MainWindow : Window { 
      public MainWindow() { 
         InitializeComponent(); 
      } 
   } 
    
   public class MyMarkupExtension : MarkupExtension { 
      public MyMarkupExtension() { } 
      public String FirstStr { get; set; } 
      public String SecondStr { get; set; }  
        
      public override object ProvideValue(IServiceProvider serviceProvider) { 
        return FirstStr + " " + SecondStr; 
      } 
   } 
}

xaml中代码

<Window x:Class = "XAMLMarkupExtension.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:my = "clr-namespace:XAMLMarkupExtension" 
   Title = "MainWindow" Height = "350" Width = "525"> 
    
   <Grid> 
      <Button Content = "{my:MyMarkupExtension FirstStr = Markup, SecondStr = Extension}" Width = "200" Height = "20" /> 
   </Grid> 
    
</Window>

让我们来运行这个应用程序,您可以在MainWindow中立即看到“标记扩展名”已成功地用作按钮的内容。

 

 

底层的类对象模型

posted @ 2022-07-09 03:27  小林野夫  阅读(426)  评论(0编辑  收藏  举报
原文链接:https://www.cnblogs.com/cdaniu/