1. 程式人生 > >WPF 之 XAML語法,物件屬性賦值(簡單賦值、TypeConverter 標籤屬性與物件屬性對映、標記擴充套件),引用外部庫

WPF 之 XAML語法,物件屬性賦值(簡單賦值、TypeConverter 標籤屬性與物件屬性對映、標記擴充套件),引用外部庫

一、XAML樹形結構

      框架都是樹形的,以<Window>物件為根節點,一層一層向下包含。這種樹形結構對於WPF整個體系都具有非常重要的意義,它不但影響著UI的佈局設計,還深刻的影響著WPF的屬性(Property)子系統和事件(Event)子系統等方方面面。在實際的程式設計過程中,我們經常要在這棵樹上進行按名稱查詢元素,獲取父/子節點等操作,為了方便操作這棵樹,WPF基本類庫為程式設計師準備了 VisualTreeHelper LogicTreeHelper 兩個助手類(Helper Class),同時還在一些重要的基類裡封裝了一些專門用於操作這棵樹的方法。

<Window  x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="532" Loaded="Window_Loaded">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="250*" />
            <ColumnDefinition Width="266*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="42" />
            <RowDefinition Height="48" />
            <RowDefinition Height="66" />
            <RowDefinition Height="153" />
        </Grid.RowDefinitions>
        <TextBox  HorizontalAlignment="Center" Margin="10,10,0,0" Name="textBox1" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
        <TextBox  HorizontalAlignment="Center" Margin="10,10,0,0" Name="textBox2" VerticalAlignment="Top"  Grid.Row="1" Grid.ColumnSpan="2"/>
        <TextBox HorizontalAlignment="Right" Margin="10,10,0,0" Name="textBox3" VerticalAlignment="Top"  Grid.Row="2" Grid.Column="0"/>
        <TextBox  HorizontalAlignment="Left" Margin="10,10,0,0" Name="textBox4" VerticalAlignment="Top"  Grid.Row="2" Grid.Column="1"/>
        <Button   HorizontalAlignment="Center" Margin="10,10,0,0" Name="button1" VerticalAlignment="Top" Grid.Row="3" Grid.ColumnSpan="2">
        </Button>
    </Grid>
</Window>

二、XAML中為物件屬性賦值的方法

XAML是一種宣告性語言,XAML會為每一個標籤建立一個與之對於的物件,物件建立之後要對它的屬性進行必要的初始化之後才有使用意義。因為XAML語言不能夠編寫程式的執行邏輯,所以一份XAML文件除了使用標籤宣告物件就是初始化物件屬性了。

注意:

XAML中對物件賦值總共有兩種方法:

1、:使用字串進行簡單賦值。

2、:使用屬性元素(Property Element)進行復雜賦值 (使用TypeConverter類將XAML標籤的Attribute與物件的Property進行對映)。


使用TypeConverter類將XAML標籤的Attribute

物件的Property進行對映TypeConverter 和 TypeConvertAttribute 這兩個類

    (1)建立類Human,型別轉換器TypeConvertAttribute

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace WpfApplication1
{
    //型別轉換器TypeConvertAttribute
    [TypeConverter(typeof(StringToHumanTypeConverter))]  
     public class Human  
     {  
         public string Name{get;set;}  
         public Human Child { get; set; }  
     } 
}


(2)、從TypeConvert派生出自己的類,並重寫它的ConverFrom方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace WpfApplication1
{
    //首先,我們要從TypeConvert派生出自己的類,並重寫它的ConverFrom方法。
    //這個方法有一個引數名叫做Value,這個值就是XAML文件裡面為其設定的值。我們要做的就是將這個值翻譯成合適物件的值並賦值給物件的屬性:
    public class StringToHumanTypeConverter : TypeConverter
    {
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                Human human = new Human();
                human.Name = value as string;
                return human;
            }
            return base.ConvertFrom(context, culture, value);
        }
    }

}

(3)XAML引用名稱空間,呼叫類

引用名稱空間:WpfApplication1

xmlns:local="clr-namespace:WpfApplication1"


       Window.Resources 定義一個Window級的Resources ,這只是一種以Window級的資源的定義.

        其實Resources的定義可以在每一個容器控制元件中,(或者是在每一個控制元件,在Template 中可以用到),像C#中變數的定義一樣,Resource的定義的地方不同
也就決定它的作用範圍,如:

       Window.Resources它的作用範圍就是在Window容器裡的所有子控制元件有效,也只有這些只控制元件才能引用/呼叫這些資源

       Grid.Resources它的作用範圍就是在Grid容器裡的所有子控制元件有效,也只有這些只控制元件才能引用/呼叫這些資源

以此類推....

       請注意:Window不是最上層的"容器",最上層的應該是Appication ,所以Application.Resources 的作用範圍更大(有人把Application.Resource叫作全域性資源,所有在這個Application下的容器控制元件等都可以使用,常用來做一個應該程式的Skin ,其ResourceDictionary定義的資源也類似 )
 
        (<<我眼裡的XAML結構框架>>概括為:"一個Application下有多個Window ,一個Window下有一個Grid,一個Grid下有很多佈局容器,這些容器裡面有好子容器或控制元件 ,控制元件裡面有Template,template裡面又可以裡Grid……  ")

(4)按鈕事件

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            Human human = (Human)this.FindResource("human123");
            MessageBox.Show(human.Child.Name);
        }



標記擴充套件:有一對花括號及其括起來的內容組成,XAML編譯器會對這樣的內容做解析、生成相應的物件。

        <TextBox Margin="5" Text="{Binding ElementName=slider1, Path=Value}" />
        <Slider x:Name="slider1" Margin="5"/>


 三、其他XAML語法

(1)引用外部庫

      clr-namespace:名稱空間名稱;assembly=外部*.dll

(2) 訪問修飾符

<Window x:Class="WpfApplication1.MainWindow" x:ClassModifier="internal"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Height="100" Width="100" x:FieldModifier="public"/>
    </Grid>
</Window>

(3)屬性元素

       為屬性賦予複雜物件。

        <Button Height="100" Width="100" Content="OK">
            <Button.Background>
                <LinearGradientBrush>
                    <GradientStop Color="DarkGreen" Offset="0"/>
                    <GradientStop Color="LightGreen" Offset="1"/>
                </LinearGradientBrush>
            </Button.Background>

        </Button>

(4) 附加屬性

        在WPF佈局管理器類(Grid、DockPanel等)中 定位 UI元素

    <Canvas>
        <Button Canvas.Top="40"/>
    </Canvas>

(5)標記擴充套件

XAML 解析器從專門的 外部類 中獲取屬性的值。這是非常有好處的,因為有些屬性需要一些程式碼語句來計算其值。

前言:XAML有時需要一些標準功能或者預設行為無法滿足的功能,比如屬性賦值,它可能並不是直接賦一個字串,而是要對已定義的物件的一個引用,由此便誕生了標記擴充套件。

標記擴充套件的語法是使用“{}”,例如 Map={bindingelementname=”myMap“}

標記擴充套件可分為以下幾類:

a、基於WPF的標記擴充套件

StaticResource:通過引用已定義資源的值來為XAML屬性提供值。

DynamicResource:通過將資源的引用推遲到執行時來為XAML屬性提供值。動態資源引用強制來每次訪問此類資源時都進行重新訪問。

Binding:按引用於元素的資料上下文來為屬性提供資料繫結值。

RelativeSource:在執行時,為了可以在元素樹中定位若干可能關係的Binding提供源資訊。

TemplateBinding:提供資料模板繫結。

b、XAML定義的標記擴充套件

x:Type:為所提供的型別提供Type物件。

x:Static:為屬性值提供已定義的靜態值。該靜態值必須在引用之前定義。

x:Null:將null指定為XAML屬性的值。

x:Array:為XAML中常規陣列的建立提供支援