【Avalonia学习笔记】1:数据绑定(Data Binding)的基本使用
1 简述数据绑定数据绑定(Data Binding)常用于将程序中的数据对象绑定到UI上,当程序中数据发生变化时让UI上显示的内容也跟着变化,或者当用户在UI上操作时就将程序中的后台数据也同步变化。Vue中也有类似的功能,只是Vue默认就做了双向数据绑定,但是Avalonia和WPF中不是这样,而且需要手动注册通知才能在数据set时候通知使用者(从这个角度看又很像是Qt的“信号槽”的封装)。使..
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.xaml
的Content
(实际上也就是双标签里面的内容),绑定自其DataContext
属性的对象(这里即是刚刚创建的MainWindow_VM
类的对象)的Content
属性。
2.2 为其嵌套DataTemplate
当为控件的*Template
属性(如ContentTemplate
、ItemTemplate
)设置为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.cs
的AddItem()
方法,而这放在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
下),然后实现其中的Convert
和ConvertBack
方法。这里先不深究了。
6.3 内置的Converter
见官方文档中的描述。
更多推荐
所有评论(0)