WPF应用程序XAML

发布于:2024-05-10 ⋅ 阅读:(28) ⋅ 点赞:(0)
<Window x:Class="WpfStringResources.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:WpfStringResources"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <system:String x:Key="name1">床前明月光,</system:String>
        <system:String x:Key="name2">疑是地上霜。</system:String>
        <system:String x:Key="name3">举头望明月,</system:String>
        <system:String x:Key="name4">低头思故乡。</system:String>
    </Window.Resources>

    <Grid>
        
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
     <TextBlock x:Name="name1" Text="{StaticResource ResourceKey=name1}" Margin="90,70"/>
     <TextBlock Text="{StaticResource ResourceKey=name2}" Margin="90,70"  Grid.Column="1"/>
     <TextBlock Text="{DynamicResource ResourceKey=name3}" Margin="90,70" Grid.Row="1" />
     <TextBlock Text="{DynamicResource ResourceKey=name4}" Margin="90,70" Grid.Row="1" Grid.Column="1"/>
            
    </Grid>
    
</Window>
<!--在讲解代码前,首先了解一下关于标记扩展和命名空间的相关知识。标记扩展主要为了属性赋值,当为元素属性Attribute赋值时,使用左右花括号来将标记扩展与XAML处理器区分开,
    本实例代码中为TextBlock的Text属性赋值时,就使用了如下标记扩展:
Text="{StaticResource ResourceKey=name2}"
其中,StaticResource ResourceKey=name2就是标记扩展,这里是属性特定于WPF的标记扩展,本实例主要使用了支持资源引用的标记扩展StaticResource和DynamicResource,
    后面的实例中还会介绍用于数据绑定的标记扩展Binding等其他标记扩展。StaticResource主要用于将已定义的资源赋值给XAML属性;DynamicResource用于将定义的资源推迟赋值给XAML属性值。
当WPF应用程序创建完成后,打开MainWindow.xaml文件,在XAML编辑器中就可以发现两个xmlns声明如下:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
其中,第一个声明表示将整个WPF命名空间映射为默认的命名空间,第二个声明则表示将XAML命名空间映射为x:前缀,其中x:前缀属于标记扩展。x:前缀有如下几个常用的标记。
(1)x:Key:为每个资源设置一个唯一标识,例如,本实例代码中的x:Key="name1"。设置此标记后,就可以将TextBlock控件的Text属性与该标识对应的String关联上。
(2)x:Name:为运行时实例指定变量名称。例如,本实例代码中的x:Name="name1",在MainWindow类中就可以通过name1作为变量名来访问XAML中定义的TextBlock对象了。
(3)x:Class:为XAML代码中提供CLR命名空间和类名。例如,XAML代码中的第一行:x:Class="WpfStringResources.MainWindow"
此处涉及XAML代码隐藏,在一个WPF项目中,XAML被编写在.xaml后缀的文件中,而C#编写的代码则编写在后缀为.xaml.cs文件中,该文件为代码隐藏文件。
    编译器在编译XAML文件时,XAML代码会通过以“命名空间.类名”的形式为根元素的x:Class属性赋值,指定隐藏文件的位置。通过这种方法将XAML代码与C#代码关联起来。
(4)x:Type:将模板或类型指定在某种类型上。
(5)x:Static:在XAML中获取类型中定义的静态变量。
(6)x:ArrayExtension:用于在XAML中创建数组。
(7)x:Null:设置某个属性值为空。
第4至第7种标记的用法将在后面的实例中讲解。
使用xmlns前缀,将命名空间和程序集映射到自定义标记中,本实例中使用了如下代码:
xmlns:system="clr-namespace:System;assembly=mscorlib"
此代码表示将System命名空间和mscorlib程序集映射到“system:”,其中“clr-namespace:”标记表示要映射的CLR命名空间,而“assembly=”是指包含CLR命名空间的程序集名称。
了解了XAML的基础知识后,下面简单介绍Grid控件的用法。当WPF应用程序创建好后,系统会自动添加一个Grid控件到窗体上,通过Grid控件能够方便地对界面进行布局。
    本实例代码中为Grid控件添加了两行两列,
    分别用RowDefinitions属性和ColumnDefinitions属性表示行的集合和列的集合,集合中有RowDefinition成员和ColumnDefinition成员分别表示每一行和每一列的元素,
    其中RowDefinition成员有Height属性,表示该行的高度,ColumnDefinition成员有Width属性,表示每一列的宽度。其中,Height和Width的值有三种表示形式。
(1)绝对大小:例如Height="100",表示行的绝对高度为100。窗体大小的改变不影响该行的高度变化。
(2)比例大小:例如Height="100*",表示行的相对高度为100,如果另一行的高度为"200*",Grid的高度为600,那么这两行的高度分别为200和400。
(3)自动大小:例如Height="auto",表示该行的高度根据内容自动调整。-->

 

     当WPF应用程序创建好后,系统会自动添加一个Grid控件到窗体上,通过Grid控件能够方便地对界面进行布局.下面代码中为Grid控件添加了两行两列,分别用RowDefinitions属性ColumnDefinitions属性表示行的集合和列的集合,集合中有RowDefinition成员和ColumnDefinition成员分别表示每一行和每一列的元素。Height和Width的值有三种表示形式:
(1)绝对大小:例如Height="100",表示行的绝对高度为100。窗体大小的改变不影响该行的高度变化。
(2)比例大小:例如Height="100*",表示行的相对高度为100,如果另一行的高度为"200*",Grid的高度为600,那么这两行的高度分别为200和400。
(3)自动大小:例如Height="auto",表示该行的高度根据内容自动调整。 

 <Grid.RowDefinitions>
     <RowDefinition Height="2*" />
     <RowDefinition Height="1*" />
 </Grid.RowDefinitions>
 <Grid.ColumnDefinitions>
     <ColumnDefinition Width="1*" />
     <ColumnDefinition Width="2*" />

Grid.RowDefinitions

  • 这里定义了两个行 (RowDefinition)。
  • 第一个行 (<RowDefinition Height="2*" />) 的高度被设置为 "2*",这意味着它将占用两倍的可用垂直空间,相比于其他使用星号 (*) 定义的行。
  • 第二个行 (<RowDefinition Height="1*" />) 的高度被设置为 "1*",它将占用剩余的一倍可用垂直空间。

Grid.ColumnDefinitions

  • 这里定义了两个列 (ColumnDefinition)。
  • 第一个列 (<ColumnDefinition Width="1*" />) 的宽度被设置为 "1*",即它将占用一倍的可用水平空间。
  • 第二个列 (<ColumnDefinition Width="2*" />) 的宽度被设置为 "2*",即它将占用两倍的可用水平空间。

示例布局

假设 Grid 控件的可用高度是 300 单位,可用宽度是 300 单位(这仅仅是为了示例,实际值取决于 Grid 控件的布局上下文):

  • 第一个行的高度将是 200 单位(因为 2/3 * 300 = 200)。
  • 第二个行的高度将是 100 单位(因为 1/3 * 300 = 100)。
  • 第一个列的宽度将是 100 单位(因为 1/3 * 300 = 100)。
  • 第二个列的宽度将是 200 单位(因为 2/3 * 300 = 200)。

-------------------------- 

<Button Content="红色" Background="Lime" Name="button1" Click="button1_Click" Margin="100"/>
该元素表示在WPF窗体中添加一个Button按钮,并通过设置元素的属性来设置按钮的属性,此处要注意XAML中元素的属性Attribute类成员的属性Property之间的区分。XAML语句Button元素中的Content属性对应Button成员的Content属性,表示按钮上显示的内容,同样的对应关系,Background属性表示Button的背景颜色,Name属性表示Button的类型变量名,Click表示Button的单击事件,Margin则表示Button显示区域与其所在窗口的边距。当在XAML编辑器中输入Click的时候,按下键盘上的Table键,XAML编辑器上会自动生成代码Click=" ",并在旁边显示一个提示按钮,显示“新建事件处理程序”,双击该按钮之后,系统会自动在MainWindow.xaml.cs文件中生成事件处理函数。 

从元素的实现代码中可以看出,元素属性赋值使用的都是字符串,对于一个元素的某些属性,如果不能用字符串来表示,则必须用到属性元素语法。属性元素语法即用属性元素本身为该属性赋值,属性语法结构为<类型.属性>,Button类的另一种表示方法如下:
<Button Name="button1" Click="button1_Click">
         <Button.Content>红色</Button.Content>
         <Button.Margin>100</Button.Margin>
         <Button.Background>
             <SolidColorBrush Color="Lime"/>
         </Button.Background>
     </Button>

------------------------------------------

标记扩展主要为了属性赋值,当为元素属性Attribute赋值时,使用左右花括号来将标记扩展与XAML处理器区分开,本实例代码中为TextBlock的Text属性赋值时,就使用了如下标记扩展:

Text="{StaticResource ResourceKey=name2}" 其中,StaticResource ResourceKey=name2就是标记扩展,这里是属性特定于WPF的标记扩展 。StaticResource主要用于将已定义的资源赋值给XAML属性;DynamicResource用于将定义的资源推迟赋值给XAML属性值。 用于数据绑定的标记扩展Binding.

-----------------------------------------------

当WPF应用程序创建完成后,打开MainWindow.xaml文件,在XAML编辑器中就可以发现两个xmlns声明如下:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
其中,第一个声明表示将整个WPF命名空间映射为默认的命名空间,第二个声明则表示将XAML命名空间映射为x:前缀,其中x:前缀属于标记扩展。x:前缀有如下几个常用的标记。

(1)x:Key:为每个资源设置一个唯一标识,例如代码 x:Key="name1"。设置此标记后,就可以将TextBlock控件的Text属性与该标识对应的String关联上。
(2)x:Name:为运行时实例指定变量名称。例如代码 x:Name="name1",在MainWindow类中就可以通过name1作为变量名来访问XAML中定义的TextBlock对象了。
(3)x:Class:为XAML代码中提供CLR命名空间和类名。例如,XAML代码:
x:Class="WpfStringResources.MainWindow" 

在一个WPF项目中,XAML被编写在.xaml后缀的文件中,而C#编写的代码则编写在后缀为.xaml.cs文件中,该文件为代码隐藏文件。编译器在编译XAML文件时,XAML代码会通过以“命名空间.类名”的形式为根元素的x:Class属性赋值,指定隐藏文件的位置。通过这种方法将XAML代码与C#代码关联起来。 

(4)x:Type:将模板或类型指定在某种类型上。
(5)x:Static:在XAML中获取类型中定义的静态变量。
(6)x:ArrayExtension:用于在XAML中创建数组。
(7)x:Null:设置某个属性值为空。

---------------------------------------------------

xmlns:system="clr-namespace:System;assembly=mscorlib"
此代码表示将System命名空间和mscorlib程序集映射到“system:”,其中“clr-namespace:”标记表示要映射的CLR命名空间,而“assembly=”是指包含CLR命名空间的程序集名称。

----------------------------------------------

<Window x:Class="WpfTextBinding.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"
        
       
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <!--在设置Text属性的引号内使用左右花括号将扩展标记括起来-->
        <!--设置Binding的ElementName属性为需要绑定的控件-->
        <!--设置Path属性为需要绑定的控件属性名称-->
        <!--设置Mode属性为绑定的方式-->
        <TextBlock Text="Text1" FontSize="20" />
        <TextBox Name="textBox1" Margin="60" FontSize="20" Text="{Binding ElementName = textBox2, Path = Text, Mode=OneWay}"/>
        <TextBlock Text="Text2" FontSize="20" Grid.Column="1" />
        <TextBox Name="textBox2" Margin="60" FontSize="20" Grid.Column="1" Text="{Binding ElementName = textBox3, Path = Text, Mode=TwoWay}"/>
        <TextBlock Text="Text3" FontSize="20" Grid.Row="1" />
        <TextBox Name="textBox3" Margin="60" FontSize="20" Grid.Row="1" Text="{Binding ElementName = textBox4, Path = Text, Mode=OneWayToSource}"/>
        <TextBlock Text="Text4" FontSize="20" Grid.Row="1" Grid.Column="1" />
        <TextBox Name="textBox4" Margin="60" FontSize="20" Grid.Row="1" Grid.Column="1" Text="{Binding ElementName = textBox1, Path = Text, Mode=OneTime}"/>
    </Grid>
</Window>
<!--本实例代码主要使用WPF扩展标记Binding实现了控件的数据绑定功能。也实现了TextBox控件的Text程序的互相绑定,在设置Text属性的引号内使用左右花括号将扩展标记括起来,
    设置Binding的ElementName属性为需要绑定的控件,设置Path属性为需要绑定的控件属性名称,设置Mode属性为绑定的方式。Mode有四种常用的绑定方式。
(1)OneWay:表示源控件影响目标控件。正如实例中的Text1的Text属性绑定到Text2的Text属性上,那么Text1为目标控件,Text2为源控件,Text2的Text属性发生改变会影响Text1的Text属性同步发生改变。
(2)TwoWay:表示源控件和目标控件互相影响。如Text2与Text3之间的互相影响。
(3)OneWaySource:表示目标控件影响源控件。如Text3影响Text4。
(4)OneTime:表示只绑定一次。-->
<!--在 WPF (Windows Presentation Foundation) 中,OneWaySource 不是一个标准的绑定模式,但你可能是在提到或误解了 OneWay 
    或其他与数据绑定相关的概念。在 WPF 中,数据绑定的主要模式有四种:

OneWay: 当源属性更改时,目标属性会更新,但更改目标属性不会影响源属性。
TwoWay: 当源属性或目标属性更改时,另一方都会更新。
OneTime: 当绑定创建时,目标属性会从源属性获取值,但之后不会有进一步的更新。
OneWayToSource: 当目标属性更改时,源属性会更新,但更改源属性不会影响目标属性。-->

代码实现四个文本控件互相绑定文本属性。当在第一个文本控件中输入文本时,其他文本控件不发生改变;当在第二个文本控件中输入文本时,第一个文本控件的文本显示与第二个同步更新;当第三个文本控件获取输入焦点时,第三个文本控件中的文本马上更新,如果在第三个文本控件中输入文本时,第一个和第二个文本控件都发生同步更新;当第四个文本控件获取输入焦点时,第四个文本控件中的文本发生更新,但在第四个文本控件中输入文本时,其他几个文本控件都没有更新。  

 

<!--在设置Text属性的引号内使用左右花括号将扩展标记括起来-->
<!--设置Binding的ElementName属性为需要绑定的控件-->
<!--设置Path属性为需要绑定的控件属性名称-->
<!--设置Mode属性为绑定的方式--> 

 <TextBlock Text="Text1" FontSize="20" />
 <TextBox Name="textBox1" Margin="60" FontSize="20" Text="{Binding ElementName = textBox2, Path = Text, Mode=OneWay}"/>
 <TextBlock Text="Text2" FontSize="20" Grid.Column="1" />
 <TextBox Name="textBox2" Margin="60" FontSize="20" Grid.Column="1" Text="{Binding ElementName = textBox3, Path = Text, Mode=TwoWay}"/>
 <TextBlock Text="Text3" FontSize="20" Grid.Row="1" />
 <TextBox Name="textBox3" Margin="60" FontSize="20" Grid.Row="1" Text="{Binding ElementName = textBox4, Path = Text, Mode=OneWayToSource}"/>
 <TextBlock Text="Text4" FontSize="20" Grid.Row="1" Grid.Column="1" />
 <TextBox Name="textBox4" Margin="60" FontSize="20" Grid.Row="1" Grid.Column="1" Text="{Binding ElementName = textBox1, Path = Text, Mode=OneTime}"/> 

本实例代码主要使用WPF扩展标记Binding实现了控件的数据绑定功能。也实现了TextBox控件的Text程序的互相绑定。 Mode有四种常用的绑定方式。
(1)OneWay:表示源控件影响目标控件。正如实例中的Text1的Text属性绑定到Text2的Text属性上,那么Text1为目标控件,Text2为源控件,Text2的Text属性发生改变会影响Text1的Text属性同步发生改变。
(2)TwoWay:表示源控件和目标控件互相影响。如Text2与Text3之间的互相影响。
(3)OneWaySource:表示目标控件影响源控件。如Text3影响Text4。
(4)OneTime:表示只绑定一次。

------------------------------------------------------- 

Style元素中的x:Key属性就是前面介绍的标记扩展,表示样式的唯一标识,当Button元素需要应用某种样式时,就将该Button的Style属性设置为该样式的x:Key的值 

<Window x:Class="WpfButtonStyle.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"
        
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <!--Style的Setters属性为Setter集合,可以为Style定义一系列的Setter来设置应用了该样式的控件-->
        <!--Setter一般用到了两个属性,一个是Property,表示控件的属性名称,另一个是Value,表示控件的属性值-->
        <Style x:Key="Style1" TargetType="Button">
            <Setter Property="Background" Value="Red"/>
            <Setter Property="Margin" Value="20"/>
        </Style>
        <!--Style的BaseOn属性,该属性表示该样式所继承的样式,实例代码中,style2继承了style1,style3和style4都继承了style2-->
        <!--如果子样式中含有和父样式相同的属性,则子样式中的该属性值会覆盖掉父样式中该属性的值-->
        <Style x:Key="Style2" TargetType="Button" BasedOn="{StaticResource ResourceKey=Style1}">
            <Setter Property="Background" Value="Orange"/>
            <Setter Property="FontSize" Value="24"/>
        </Style>
        <!--在Button3中内嵌了样式资源,但内嵌样式资源并没有生效-->
        <Style x:Key="Style3" TargetType="Button" BasedOn="{StaticResource ResourceKey=Style2}">
            <Style.Triggers>
                <!--触发器所绑定的是Button控件的IsMouseOver属性,当IsMouseOver属性值为True时,则触发该触发器,
                设置Button的背景为黄色。MultiTrigger类则表示多条件触发器,原理与Trigger类类似,只是它可以设置多个条件,
                当多个条件都满足时,才触发Setter改变控件样式-->
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="Yellow"/>
                    <Setter Property="FontSize" Value="70"/>
                </Trigger>
            </Style.Triggers>
        </Style>
        <Style x:Key="Style4" TargetType="Button" BasedOn="{StaticResource ResourceKey=Style2}">
            <Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsMouseOver" Value="True"/>
                        <Condition Property="IsPressed" Value="True"/>
                    </MultiTrigger.Conditions>
                    <Setter Property="Background" Value="LightGreen"/>
                    <Setter Property="FontSize" Value="60"/>
                </MultiTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <!--如果子样式中含有和父样式相同的属性,则子样式中的该属性值会覆盖掉父样式中该属性的值。
        另外,还可以看到,Button2应用了样式style2,style2中定义了Backgroud属性,而Button2中也为Background属性赋值了,
        从按钮二显示的效果可以看出,Button2的Background属性是以Button2中设置的值为准。
在Button3中内嵌了样式资源,但内嵌样式资源并没有生效。从以上效果可以说明,子类中的样式可以覆盖父类中的样式,
        而按钮属性中设置的值优先于样式中设置的属性值,样式中设置的属性值优先于内嵌样式中设置的属性值。-->
        <Button Style="{StaticResource ResourceKey=Style1}" Name="Button1" Content="第一个按钮"/>
        <Button Style="{StaticResource ResourceKey=Style2}" Name="Button2" Content="第二个按钮" Grid.Column="1" Background="Lime"/>
        <Button Style="{StaticResource ResourceKey=Style3}" Name="Button3" Content="第三个按钮" Grid.Row="1">
            <Button.Resources>
                <Style TargetType="Button">
                    <Setter Property="Background" Value="Yellow"/>
                </Style>
            </Button.Resources>
        </Button>
        <Button Style="{StaticResource ResourceKey=Style4}" Name="Button4" Content="第四个按钮" Grid.Row="1" Grid.Column="1"/>
    </Grid>
</Window>

MainWindow 2024-05-05