UWP Binding和x:Bind數據綁定

前言

{x:bind}是隨着UWP被推出而被添加的,可以說是Win10 UWP開發專有擴展。雖然 {x:Bind} 缺少{Binding} 中的一些功能,但它運行時所花費的時間和使用的內存量均比 {Binding} 要少,且支持更好的調試。

使用Binding綁定

屬性 說明
Path 用於指定綁定的數據源的屬性
例:Text="{Binding Name}"
Mode

綁定模式,Mode一共有三種,OneTime,OneWay,TwoWay,默認值爲OneWay

OneTime:只綁定一次

OneWay:單向綁定

TwoWay:雙向綁定

例:Text="{Binding Name, Mode=OneTime}"

RelativeSource

RelativeSource是一種相對關係找數據源的綁定。目前有兩種:Self和TemplatedParent

Self:目標元素應用作此綁定的源。當要將元素的一個屬性綁定到同一元素的另一個屬性時,就使用該模式

TemplatedParent:指定引用了該 ControlTemplate模板資源的控件是此綁定的源

ElementName

用於綁定元素,可用於兩個控件屬性相互綁定,需要注意兩點:

指定的ElementName必須在當前XAML名稱範圍裏

如果綁定目標位於數據模板或控件模板中,則爲模板化父級的XAML名稱範圍

Source

用於指定綁定的對象,不設定明確的綁定source,這樣Binding就去從本控件類爲開始根據可視樹的層次結構自下而上查找不爲空的Datacontext屬性的值作爲數據源

Source,ElementName和RelativeSource三者是互斥的,指定多餘一種的綁定方式會引發異常

Converter 轉換器,在對象值和我們綁定目標的類型不一致時進行轉換

ConverterParameter

指定可在轉換器邏輯中使用的轉換器參數,參數不能綁定只能指定常量值傳入轉換器中
ConverterLanguage 指定轉換器要使用的區域性,不能綁定只能指定常量值傳入轉換器中
FallbackValue FallbackValue的用途是:當綁定對象不存在時,我們就使用FallbackValue的值
TargetNullValue TargetNullValue的用途是:當綁定對象爲空時,我們就使用TargetNullValue的值
UpdateSourceTrigger UpdateSourceTrigger的值有三種:Default,PropertyChanged,Explicit

Converter轉換器的使用

使用轉換器我們要實現IValueConverter接口:

public class BoolVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        bool? result = value as Nullable<bool>;
        if(result == true)
        {
            return Visibility.Visible;
        }
        return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

如果你的值需要轉換回去,你也可以繼續實現ConvertBack方法

<Page> 
  <Page.Resources> 
    <local:BoolVisibilityConverter x:Key="BoolVisibilityConverter"/> 
  </Page.Resources> 
  <Grid> 
    <Border Visibility="{Binding Busy, Converter={StaticResource BoolVisibilityConverter}}"/> 
  </Grid> 
</Page>

ConverterParameter和ConverterLanguage

<Border Visibility="{Binding Busy, Converter={StaticResource BoolVisibilityConverter}, 
  ConverterParameter=One, ConverterLanguage=en-US}"/>

 

使用x:Bind綁定

屬性 說明
Path 用於指定綁定的數據源的屬性
例:Text="{x:Bind Name}"
Mode

綁定模式,Mode一共有三種,OneTime,OneWay,TwoWay,默認值爲OneTime

OneTime:只綁定一次

OneWay:單向綁定

TwoWay:雙向綁定

例:Text="{x:Bind Name, Mode=OneWay}"

BindBack 支持從目標類型轉換到數據源類型,類似轉換器IValueConverter的ConvertBack方法功能
Converter 轉換器,在對象值和我們綁定目標的類型不一致時進行轉換

ConverterParameter

指定可在轉換器邏輯中使用的轉換器參數,參數不能綁定只能指定常量值傳入轉換器中
ConverterLanguage 指定轉換器要使用的區域性,不能綁定只能指定常量值傳入轉換器中
FallbackValue FallbackValue的用途是:當綁定對象不存在時,我們就使用FallbackValue的值
TargetNullValue TargetNullValue的用途是:當綁定對象爲空時,我們就使用TargetNullValue的值
UpdateSourceTrigger UpdateSourceTrigger的值有三種:Default,PropertyChanged,Explicit

x:Bind 的數據源

與傳統Binding綁定較大的區別,是 x:Bind 的數據源爲當前 View(即頁面 Page 或用戶控件UserControl)自身,也就是說,它使用 Page 或 User Control 的實例爲作數據源;因此如果你設置了 Path 屬性, x:Bind 會到當前 Code-Bebind 類中找對應名稱的成員(屬性、字段、方法)

在傳統Binding綁定中,Binding 的數據源可以通過四種形式指定,它們分別是 DataContext(默認)、RelativeSource、Source、ElementName。而 x:Bind 既然將當前 View 的實例作爲唯一數據源,那麼我們就完全不需要像傳統 Binding 一樣設置 DataContext;而對於後面三種設置數據源的方式, x:Bind 也僅支持以下兩種情況:

ElementName      
    x:Bind -> {x:Bind slider1.Value}      
    Binding -> {Binding Value, ElementName=slider1}   

RelativeSource: Self      
    x:Bind -> <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... />        
    Binding -> <Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... /> 

綁定模式

x:Bind 的 Binding Mode 值有以下三項:OneWay、OneTime、TwoWay;它的默認值是 OneTime,OneTime 的意思是僅在界面初始化時去初始化界面中的綁定

更具體來說,x:Bind 的綁定是在 Page 或 User Control 的 Loading 事件中初始化的;也就是說,在 Mode=OneTime(默認值)時,僅當一個屬性值的設置在 View 的構造函數中時(在 Loading 事件之前)纔會在 x:Bind 初始化中被更新到 UI 中;在其它位置(如 Loaded 事件或某一操作的響應事件中等等)修改此屬性的值,都不會再被更新(即使調用了 INotifyPropertyChanged 中的 PropertyChanged 事件)

轉換(Converting)

在數據源屬性類型和綁定目標屬性類型不一致時,如果我們使用傳統的 Binding,可以將一個實現了 IValueConverter 的對象設置到 Binding 的 Converter 屬性來實現值的轉換。而使用 x:Bind,除了這種方式之外,還有更方便的——綁定屬性到函數。也就是說,你可以將一個函數放到 x:Bind 中。當然,x:Bind 仍然是在當前 View 的 Code-Behind 代碼中來找所指定的函數。參考如下代碼:

<Border
    x:Name="border"
    Background="{x:Bind GetBrush(IsPass), Mode=OneWay}">
    <Image Margin="20" Source="{x:Bind GetImage(IsPass), Mode=OneWay}" />
</Border>
   public Brush GetBrush(bool isPass)
    {
        return isPass ? new SolidColorBrush(Colors.LimeGreen) : new SolidColorBrush(Colors.Crimson);
    }

    private ImageSource GetImage(bool isPass)
    {
        return isPass ? new BitmapImage(new Uri("ms-appx:///Assets/Happy.png")) : new BitmapImage(new Uri("ms-appx:///Assets/Sad.png"));
    }

在上面的例子中,兩處被綁定的函數均接受一個參數,事實上,這裏支持多個參數。所以這一點也要比 IValueConverter 方便;此外,綁定屬性到函數也支持類似於 IValueConverter 中的雙向轉換,除了能從數據源類型轉換到目標類型,也支持從目標類型轉換到數據源類型,方法是使用 BindBack 屬性指定另外一個方法。

另外,還一個非常便捷的轉換是 Visibility 和 bool 之間的轉換:控件的 Visibility 可以直接綁定到一個布爾屬性或字段;當布爾值爲 true 時,Visibility 的值是 Visible,反之,是 Collapsed。參考如下代碼:

<Button Content="Logout" Visibility="{x:Bind IsLogin}" />

在 DataTemplate 中使用

爲列表控件(如 ListView 等)設置 ItemTemplate 屬性時,要用到 DataTemplate;如果在 DataTemplate 中使用 x:Bind,要怎麼做呢?

首先要爲 DataTemplate 指定 x:DataType,告訴它要展示的數據 Model 類,一般情況下,這需要引入 xmlns 命令空間;然後,在 DataTemplate 內部,使用 x:Bind 直接綁定到該 Model 的相關屬性。參考以下代碼:

<UserControl ...
    xmlns:models="using:xBindTest.Models">
    <UserControl.Resources>
        <DataTemplate x:Key="FriendItemTemplate" x:DataType="models:Friend">
            <StackPanel Margin="0,4">
                <TextBlock
                    FontSize="20"
                    FontWeight="SemiBold"
                    Text="{x:Bind Name}" />
                <TextBlock
                    Margin="{StaticResource ContentMargin}"
                    FontSize="14"
                    Text="{x:Bind Email}" />
            </StackPanel>
        </DataTemplate>
    </UserControl.Resources>
    <Grid>
        <ListView ItemTemplate="{StaticResource FriendItemTemplate}" ItemsSource="{x:Bind AllFriends}" />
    </Grid>
</UserControl>

綁定到事件

在使用傳統綁定時,對於控件操作的響應,我們一般會用到命令或行爲(當控件不支持 Command 或對控件的某一特定事件進行響應時,如 ListView 控件的 SelectionChanged 事件);然而 x:Bind 可以輕鬆地實現同樣的操作,因爲它支持綁定到事件,來看代碼:

<Button Click="{x:Bind ShowInfoTest1}" Content="Show Info" />
public void ShowInfoTest1()
{
    Info = "Update Info in method: ShowInfoTest1()";
}

像綁定屬性一樣簡單,不同的是,被綁定的不再是屬性,而是事件名,而 Path 也不是屬性名,而是方法名。相比 ICommand 或行爲對此操作的實現,要簡單的多。

這裏需要補充的是,關於方法的簽名:

  • 參數可以爲空,如:
void ShowInfoTest1()
  • 也可以與被綁定事件的簽名一致,如:
void ShowInfoTest1(object sender, RoutedEventArgs e)
  • 還可以是個數與事件簽名的個數一致,事件簽名中每個參數類型都可以轉換爲方法中所定義的參數類型,如:
void ShowInfoTest1(object sender, object e)

如果不一致,在項目編譯時就不會通過。

另外,在綁定到事件中,x:Bind 除了支持上述靈活的方法簽名,對於方法的返回值並沒有要求,不僅可以是 void,也可以是其它任何返回類型;並且也支持 async 方法的綁定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章