WPF 笔记3——在XAML中给对象属性赋值

看B站刘铁猛老师视频学习WPF

XAML语言是从xml文件派生而来,是声明式语言,一个标签就表示声明了一个对象。

对象的值可以存储在对象的字段中,也可存储在对象的属性中;

通过给对象的属性赋值,可以在赋值时检查值的合法性,如果不合法可以抛异常给提示。

在XAML中给对象的属性赋值有3中方式:

  • Attribute=value
  • 属性标签
  • 标签扩展

1、Attribute=value

优点:简单快捷

缺点:不易给属性赋复杂值


        <Rectangle Height="50" Width="200" Stroke="Red" Fill="Gold" RadiusX="20" RadiusY="10"></Rectangle> 
        
        <Path Data="M 0,0 L 200,100  L 100,200 Z" Stroke="Red" Fill="Green" ></Path>

        <!--Path对象的Data属性值稍复杂-->
        <!--两个对象中都有Stroke属性,类型是Brush-->

Path对象的Data属性是Geometry类型, Data="M 0,0 L 200,100  L 100,200 Z"实现了对Data的赋值。然而这对于人来说是既不易阅读,也不易书写。

如果属性的类型比Data还复杂,就需要使用第二种方式进行赋值了。

补充:

两个对象中都有Stroke、Fill属性,类型都是Brush;

在xaml文件中,对Stroke属性赋的是字符串,这个字符串最后都被转换Stroke对象了 

这是怎么实现的呢?

(1)在后台文件中添加Person类

public class Person
    {
        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 母亲
        /// </summary>
        public Person Mother { get; set; }
        /// <summary>
        /// 父亲
        /// </summary>
        public Person Father { get; set; }
    }

(2)在前台文件中添加资源

资源是通过key来检索的,资源中添加Person对象时候,需要指定一个key

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <!--资源是通过key来检索的,在资源中添加对象时需要指定key-->
        <local:Person x:Key="pon" Name="Jeff" ></local:Person>
    </Window.Resources>
    
    <Grid>

        <Button Width="100" Height="50" Content="Show" Click="Button_Click"></Button>

    </Grid>
</Window>

(3)编辑Button_Click事件


        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //通过key检索资源
            Person p = this.FindResource("pon") as Person;
            if (p == null)
            {
                MessageBox.Show("空对象");
            }
            else
            {
                StringBuilder sb = new StringBuilder($"姓名:{p.Name}\n");
                if (p.Mother != null)
                {
                    sb .Append($"妈妈:{p.Mother.Name}\n");
                }
                if (p.Father != null)
                {
                    sb.Append($"爸爸:{p.Father.Name}\n");
                }
                MessageBox.Show(sb.ToString());
            }
        } 

运行效果:

(4)给Person的其他属性赋值

<local:Person x:Key="pon" Name="Jeff" Mother="Anna" ></local:Person>

运行效果:

(5)报异常了,显然我们不能给复杂属性(Mother、Father) 直接使用Attribute=value方式赋值,那么怎么样才能像前文中那样Stroke="Red" Fill="Gold"?

这就需要用到System.ComponentModel.TypeConverter类了

添加声明一个新类,继承自System.ComponentModel.TypeConverter


    /// <summary>
    /// 通过重新ConvertFrom方法实现将一个简单类型,通过赋值,转换成一个复杂对象 
    /// </summary>
    public class NameToPersonTypeConvert : System.ComponentModel.TypeConverter
    {
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            string name = value.ToString();
            Person person = new Person();
            person.Name = name;
            return person;
            //return base.ConvertFrom(context, culture, value);
        }
    }

(6)下一步就是把这个类附加到Person上,

    //将NameToPersonTypeConvert类以特性方式附加到Person类上
    [TypeConverterAttribute(typeof(NameToPersonTypeConvert))]
    public class Person
    {
        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 母亲
        /// </summary>
        public Person Mother { get; set; }
        /// <summary>
        /// 父亲
        /// </summary>
        public Person Father { get; set; }
    }

运行效果:

通过以上步骤,就完成了给对象的复杂类型属性赋一个简单值 


2、属性标签

在xaml中,标签是用来声明对象的。

        <!--标签内容,是夹在开始标签和结束标签之间的部分。注意区分概念-->
        <Button Width="100" Height="50" Content="这里是对象的内容">
            这里是标签的内容
        </Button>

属性标签的格式是:<类名.属性名></类名.属性名>

缺点:代码变多

示例1:

Button的Content是object类型



        <Button Width="100" Height="50" >
            <Button.Content>
                <Rectangle Width="20" Height="20" Stroke="Green" Fill="Green"></Rectangle>
            </Button.Content>
        </Button>

示例2:

Rectangle的Fill是Brush类型

        <Rectangle Width="400"  Height="400" Stroke="Blue">
            <Rectangle.Fill>
               <!--设置渐变填充-->
                <LinearGradientBrush>
                    <LinearGradientBrush.StartPoint>
                        <!--开始位置-->
                        <Point X="0" Y="0"></Point>
                    </LinearGradientBrush.StartPoint>
                    <LinearGradientBrush.EndPoint>
                        <!--结束位置-->
                        <Point X="1" Y="1"></Point>
                    </LinearGradientBrush.EndPoint>
                    <LinearGradientBrush.GradientStops>
                        <GradientStopCollection>
                            <!--设置描述渐变中转换点的位置和颜色-->
                            <GradientStop Offset="0.1" Color="Red"></GradientStop>
                            <GradientStop Offset="0.3" Color="Yellow"></GradientStop>
                            <GradientStop Offset="0.5" Color="Green"></GradientStop>
                            <GradientStop Offset="0.7" Color="Pink"></GradientStop>
                            <GradientStop Offset="0.9" Color="Pink"></GradientStop>
                        </GradientStopCollection>
                    </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>

补充:

(1)Brush的类图关系如下:

(2)注意要点

  • 能用attribute=value方式赋值是,就不要用属性标签;
  • 如果要赋的值正好是默认值,就不要用在属性标签中写出来;
  • 对于属性标签,如果属性值是一组集合,可以不写集合的名称,直接罗列集合元素

示例2的代码可优化成这种方式:


        <Rectangle Width="400"  Height="400" Stroke="Blue">
            <Rectangle.Fill>
                <!--开始点、结束点使用attri=value方式赋值 -->
                <!-- 
                    StartPoint="0,0" EndPoint="1,1" 
                   是LinearGradientBrush 的默认值,在这里可以不写
                -->
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> 
                    <LinearGradientBrush.GradientStops> 
                            <!--属性标签是集合,可以直接罗列元素不写属性名称-->
                            <GradientStop Offset="0.1" Color="Red"></GradientStop>
                            <GradientStop Offset="0.3" Color="Yellow"></GradientStop>
                            <GradientStop Offset="0.5" Color="Green"></GradientStop>
                            <GradientStop Offset="0.7" Color="Pink"></GradientStop>
                            <GradientStop Offset="0.9" Color="Pink"></GradientStop> 
                    </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        

3、标签扩展

        标签扩展方式赋值与attribute=value赋值方式类型,只是这个value比较特殊,是花括号括起来的一组值。

        WPF中的标签扩展是有限的,我们只要掌握常用的即可
示例1

StaticResource 标签扩展

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <!--
            在资源中定义字符串,这里需要添加命名空间如下
            xmlns:sys="clr-namespace:System;assembly=mscorlib"
        -->
        <sys:String x:Key="strHello">Hello World</sys:String>
    </Window.Resources>
    <Grid>
        <!--文本框显示的字符串来自Window.Resources-->
        <TextBlock Height="30" Width="200" Background="LightYellow" Text="{StaticResource ResourceKey=strHello}"> </TextBlock>
        <TextBlock Height="30" Width="200" Background="LightPink" Text="{StaticResource strHello}" Margin="262,251,330,138"></TextBlock>
    </Grid>
</Window>

运行效果:

示例2

Binding标签扩展

    <Grid> 
        <Grid.RowDefinitions>
            <RowDefinition Height="30"></RowDefinition>
            <RowDefinition Height="3"></RowDefinition>
            <RowDefinition Height="30"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock x:Name="tb" Text="{Binding ElementName=sld,Path=Value}" Width="150" Height="25" Background="LightCoral"></TextBlock>
        <Slider x:Name="sld" Grid.Row="2" Value="50" Maximum="100" Minimum="0"  ></Slider> 
    </Grid>

运行效果:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值