《深入浅出WPF》读书笔记之——XAML篇(2)

1、XAML是一种声明式语言,通过在XAML中声明一个节点来定义对象,XAML解析器会把声明的对象解析成C#中的一个对象

2、WPF中的两颗树

  1. 逻辑树——XAML中通过声明控件形成的树

  2. 可视化树——如果把所有的控件(包含控件中包含的控件)都看作一棵树的话就是可视化树

  3. 可以使用LogicalTreeHelper和VisualTreeHelper来操作树中的节点

3、使用TypeConverter将XAML中的Attribute和C#类中的Property进行映射

    例如:有一个类

    public class Human
    {
        public string Name { get; set; }
        public Human Child { get; set; }
    }

在xaml中使用时,我想给Child属性直接赋值

<local:Human Name="TestName" Child="TestChildName"></local:Human>

而不是使用如下方式:

<local:Human x:Key="testKey" Name="TestName">

            <local:Human.Child>

                <local:Human Name="TestChildName" />

            </local:Human.Child>

        </local:Human>

就需要一个TypeConverter来实现,因为第一种方式Child属性接收的是字符串类型

先定义一个TypeConverter:

        /// <summary>
        /// 重载此方法可以在写Xaml时没有错误提示
        /// </summary>
        /// <param name="context"></param>
        /// <param name="sourceType"></param>
        /// <returns></returns>
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type  sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }
            
            return base.CanConvertFrom(context, sourceType);
        }
        /// <summary>
        /// 把字符串转换成Human对象
        /// </summary>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public override object ConvertFrom(ITypeDescriptorContext context,  CultureInfo culture, object value)
        {
            if (value is string inpuString)
            {
                return new Human()
                {
                    Name = inpuString
                };
            }
            return base.ConvertFrom(context, culture, value);
        }

然后把TypeConverter应用到Human类

    [TypeConverter(typeof(HumanTypeConverter))]
    public class Human
    {
        public string Name { get; set; }
        public Human Child { get; set; }
    }

如果不实现CanConvertFrom方法,则会报以下错误

4、标记扩展(MarkupExtensions)

    a)所谓标记扩展,实际上是一种特殊的Attribute=Value语法,特殊的地方在与Value字符串由一堆花括号及其括起来的内容组成,XAML编译器会对这样的内容作出解析,生成相应的对象,例如:

<TextBlock Text="{Binding Name, Source={StaticResource testKey}}" />

    b)尽管标记扩展的语法简洁方便,单并不是所有的对象都可以用标记扩展的语法类书写,只有MarkupExtension类的派生类(直接或间接)才能使用标记扩展语法类创建对象

    c)标记扩展是可以嵌套的,比如:

<TextBlock Text="{Binding Path=Name, RelativeSource={RelativeSource  Mode=FindAncestor,AncestorType=Grid}}" />

    d)参照下面两种写法

<TextBlock Text="{Binding Name, Source={StaticResource testKey}}" />

<TextBlock Text="{Binding Path=Name, Source={StaticResource testKey}}" />

前者中的Name为固定位置参数(Positional Parameters),后者中的Name为具名参数(Named Parameters),固定位置参数实际上是标记扩展类的构造函数的参数,其位置顺序由构造函数的参数决定

5、x:Code标签,允许在xaml文件中编写C#代码(代码必须写在CDATA标签中),但是没有智能提示,其实也没有实际意义……

    <Grid>
        <TextBlock Text="{Binding Path=Name, Source={StaticResource testKey}}" />
        <x:Code>
            <![CDATA[
            private void TestButton_Click(object sender, RoutedEventArgs e)
            {
                Human human = this.Resources["testKey"] as Human;
                MessageBox.Show(human.Child.Name);
            }
            ]]>
        </x:Code>
    </Grid>

6、xaml中的注释

    只能出现在标签的内容区域,即只能出现在开始标签和结束标签之间

    不能单独注释标签的Attribute

    不能嵌套

        <!--<local:Human x:Key="testKey" Name="TestName">
            <local:Human.Child>
                <local:Human Name="TestChildName" />
            </local:Human.Child>
        </local:Human>-->

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值