【Avalonia學習筆記】1:數據綁定(Data Binding)的基本使用

1 簡述數據綁定

數據綁定(Data Binding)常用於將程序中的數據對象綁定到UI上,當程序中數據發生變化時讓UI上顯示的內容也跟着變化,或者當用戶在UI上操作時就將程序中的後臺數據也同步變化。Vue中也有類似的功能,只是Vue默認就做了雙向數據綁定,但是Avalonia和WPF中不是這樣,而且需要手動註冊通知才能在數據set時候通知使用者(從這個角度看又很像是Qt的“信號槽”的封裝)。

使用數據綁定往往和MVVM(Model-View-ViewModel)模式的使用分不開,也就是說將M綁定到V(或者反過來,如果兩邊都做那就是雙向數據綁定)。

2 DataContext

2.1 簡述DataContext

在Avalonia中視圖層有兩種組件,一種是Window,一種是UserControl,在VS裏添加項時在Avalonia下可以選,這和WPF差不多。

兩者都是Avalonia.Controls命名空間下的,且都繼承自ContentControl類,而ContentControl類又繼承自Control類,這個類向上有一個父類StyledElement集成了DataContext這個屬性(不是字段)。

它的作用在於,在View層做數據綁定時默認綁定到這個屬性所指定的對象上。例如在App.xaml.cs中可以看到創建MainWindow時,創建了其對應的ViewModel對象,並傳入了DataContext這個屬性中:

desktop.MainWindow = new MainWindow
{
	DataContext = new MainWindow_VM(),
};

那麼在View層中,這裏也就是在MainWindow.xaml中使用數據綁定時,就會綁定到上面new MainWindow_VM()創建出的那個對象的相應屬性上去,例如:

<Window ...
        Content="{Binding Content}">
        <!-- 綁定Window.DataContext.Content -->
</Window>

就是將這個MainWindow.xamlContent(實際上也就是雙標籤裏面的內容),綁定自其DataContext屬性的對象(這裏即是剛剛創建的MainWindow_VM類的對象)的Content屬性。

2.2 爲其嵌套DataTemplate

當爲控件的*Template屬性(如ContentTemplateItemTemplate)設置爲DataTemplate即數據模板時,會自動爲DataTemplate內的控件設置DataContext屬性,例如在某UserControl中:

<!-- 綁定UserControl.DataContext.Items -->
<ItemsControl Items="{Binding Items}">
	<ItemsControl.ItemTemplate>
		<DataTemplate>
		<!-- 綁定UserControl.DataContext.Items中每一個對象的IsChecked屬性和Description屬性 -->
			<CheckBox Margin="4" IsChecked="{Binding IsChecked}" Content="{Binding Description}" />
		</DataTemplate>
	</ItemsControl.ItemTemplate>
</ItemsControl>

又如官方文檔上ContentControl的例子

3 屬性/集合變化通知

在屬性發生變化時要通知綁定它的地方也跟着變化,最原始的方式就是繼承INotifyPropertyChanged的方式。這裏用ReactiveUI實現,要繼承封裝好的ReactiveObject類,然後在完整屬性(含私有字段)的set中調用:

this.RaiseAndSetIfChanged(ref 私有字段, value);

集合變化還是直接用.Net的ObservableCollection,或者ReactiveUI的ReactiveList,詳見官方文檔說明。

4 在xaml中使用{Binding xxx}標記擴展

這裏和WPF中的用法一樣;如"{Binding Name}""{Binding Path=Name}"等價,表示綁定DataContext的Name屬性;又如"{Binding}""{Binding .}"一樣,表示使用DataContext本身作爲綁定源。在綁定的Path中遇到可迭代的內容,可以用下標選擇,如"{Binding Students[0].Name}"

使用Mode可以指定綁定的方式,如<TextBox Text="{Binding Name, Mode=TwoWay}">就將文本框和後臺DataContext的Name字段做了雙向綁定。更多Mode見官方文檔說明。

5 從其它位置綁定

默認時,綁定的是DataContext的屬性,可以手動指定綁定到其它位置。

5.1 綁定一個提供了Name的控件

可以在標記語法中使用ElementName指定綁定的控件的Name:

<TextBox Name="other">
<TextBlock Text="{Binding Text, ElementName=other}"/>

也可以簡寫成#Name的形式,類似於CSS選擇器:

<TextBox Name="other">
<TextBlock Text="{Binding #other.Text}"/>

後者是WPF裏不具備的寫法。

5.2 綁定父組件

所有同文件內的綁定都可以用5.1中的做法(只要給個Name就行了),這裏用$parent選擇器就可以向父組件選擇,其中可以在[]內用數字表示向上的層級,向上一層就是0;可以在[]內用類型名指定向上搜索的類型,詳見官方文檔的說明。

更多時候,這個選擇器應該用在綁定整個xaml文件的父組件,例如在官方文檔教程——待辦列表(TodoList)的TodoListView裏,點擊Add按鈕的命令是去調用MainWindowViewModel.csAddItem()方法,而這放在MainWindow的DataContext中,而MainWindow又是這個TodoListView的父組件,且在這個文件中體現不出來,所以要用$parent[Window].DataContext.AddItem向上搜索。

6 綁定對象的轉換

當綁定源的數據要給xaml使用時,可能需要對數據進行處理,將其類型、格式轉換掉。

6.1 取反

這個和Vue裏或者是很多模板語言裏一樣,直接用!就可以對數據進行取反,如果數據本身不是bool類型的,使用!實際上就是先調用Convert.ToBoolean將其轉換成布爾數據然後再取反,所以!!可以起到將數據轉換成布爾類型的作用。

6.2 自建的Converter

使用轉換器(Converter)可以實現更復雜的類型轉換和處理,要自建Converter,要有一個繼承IValueConverter接口的類(在Avalonia中這個接口被放在Avalonia.Data.Converters命名空間下,而不是System.Windows.Data下),然後實現其中的ConvertConvertBack方法。這裏先不深究了。

6.3 內置的Converter

官方文檔中的描述。

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