欢迎光临散文网 会员登陆 & 注册

Avalonia学习

2023-03-30 23:38 作者:忽如一夜娇妹来  | 我要投稿

2023.03.30 Avalonia学习

原文地址:https://www.firstsaofan.top/archives/20230330avalonia-xue-xi

数据绑定:变化通知

中文地址:变化通知 - Avalonia UI (gitbook.io)

英文地址:Change Notifications - Avalonia UI

建议对照着看因为有些单词翻译过来变味了,需要看原单词比较容易理解

格式字符串

你可以为绑定设置格式字符串,从而影响在UI上如何展现值:

 <!-- 选项 1: 使用花括号对格式字符串进行转义 -->
 <TextBlock Text="{Binding FloatValue, StringFormat={}{0:0.0}}" />
 
 <!-- 选项 2: 使用反斜线对格式字符串进行转义 -->
 <TextBlock Text="{Binding FloatValue, StringFormat=\{0:0.0\}}" />
 
 <!-- 选项 3: 如果格式字符串并非以{0}开始,则不需要转义 -->
 <!-- 注意:如果在格式字符串中存在空格,则需要用单引号''包裹起来 -->
 <TextBlock Text="{Binding Animals.Count, StringFormat='I have {0} animals.'}" />
 <!-- 注意: 如果格式字符串以{0}开始则需要转义,例如:-->
 <TextBlock Text="{Binding Animals.Count, StringFormat='{}{0} animals live in the farm.'}" />


StringFormat属性存在时,绑定的值将会由StringFormatValueConverter利用指定的格式字符串进行转换。

与WPF不同,你需要将格式字符串用花括号包裹起来并以0:开始({0:TheStringFormat})。如果格式字符串中花括号出现在开始,那么即使用单引号包裹起来,也需要进行转义。可以在前面加{},也可以使用反斜线\{...\}

WPF:

 <TextBlock Text="{Binding FloatValue, StringFormat=0.0}" />

Avalonia:

 <TextBlock Text="{Binding FloatValue, StringFormat={}{0:0.0}}" />
 
 <TextBlock Text="{Binding FloatValue, StringFormat=\{0:0.0\}}" />
 
 <TextBlock Text="{Binding FloatValue, StringFormat='{}{0:0.0}'}" />

格式字符串详情请阅读微软文档

编译绑定

在XAML中定义的绑定是通过反射来实现寻找和访问视图模型中的属性的。在Avalonia中你还可以使用编译绑定。这样有一些好处:

  • 如果你使用编译绑定但没有找到你想要绑定的属性,会得到编译期错误,得到更好的调试体验。

  • 众所周知,反射很慢(可以阅读codeproject.com的这篇文章)。使用编译绑定可以提升应用的性能。


开启或禁用编译绑定

编译绑定默认不开启。想要开启编译绑定,你需要先通过DataType定义想要绑定的目标的类型。在DataTemplates数据模板中有DataType属性,在其他元素中可以使用x:DataType。通常你会在根节点设置x:DataType,例如WindowUserControl。从Avalonia0.10.12开始,你还可以在Binding中直接指定DataType

现在你可以开启或禁用编译绑定,方法是设置x:CompileBindings="[True|False]"。所有的子节点都会继承这一属性,需要的时候也可以为全局开启,为特定的子节点禁用。

 <!--设置DataType并开启全局绑定 -->
 <UserControl xmlns="https://github.com/avaloniaui"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:vm="using:MyApp.ViewModels"
              x:DataType="vm:MyViewModel"
              x:CompileBindings="True">
     <StackPanel>
         <TextBlock Text="Last name:" />
         <TextBox Text="{Binding LastName}" />
         <TextBlock Text="Given name:" />
         <TextBox Text="{Binding GivenName}" />
         <TextBlock Text="E-Mail:" />
         <!-- 在绑定标记中设置DataType -->
         <TextBox Text="{Binding MailAddress, DataType={x:Type vm:MyViewModel}}" />
 
         <!-- 我们无法在编译绑定中绑定到方法,所以对于按钮需要做出让步 -->
         <Button x:CompileBindings="False"
                 Content="Send an E-Mail"
                 Command="{Binding SendEmailCommand}" />
     </StackPanel>
 </UserControl>

CompiledBinding标记

如果你不想对所有子节点开启编译绑定,也可以使用CompiledBinding标记。你仍然需要设置DataType,但可以省略x:CompileBindings="True"

 <!-- 设置 DataType -->
 <UserControl xmlns="https://github.com/avaloniaui"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:vm="using:MyApp.ViewModels"
              x:DataType="vm:MyViewModel">
     <StackPanel>
         <TextBlock Text="Last name:" />
         <!-- 使用CompiledBinding标记进行绑定 -->
         <TextBox Text="{CompiledBinding LastName}" />
         <TextBlock Text="Given name:" />
         <TextBox Text="{CompiledBinding GivenName}" />
         <TextBlock Text="E-Mail:" />
         <TextBox Text="{CompiledBinding MailAddress}" />
 
         <!-- 我们无法在编译绑定中绑定到方法,所以使用正常的绑定(Binding) -->
         <Button Content="Send an E-Mail"
                 Command="{Binding SendEmailCommand}" />
     </StackPanel>
 </UserControl>

ReflectionBinding标记

如果你在根节点开启了编译绑定(通过x:CompileBindings="True"),但对于特定的位置并不想用编译绑定,或者遇到了编译绑定的局限,你可以使用ReflectionBinding标记。

 <!-- 设置 DataType -->
 <UserControl xmlns="https://github.com/avaloniaui"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:vm="using:MyApp.ViewModels"
              x:DataType="vm:MyViewModel"
              x:CompileBindings="True">
     <StackPanel>
         <TextBlock Text="Last name:" />
         <TextBox Text="{Binding LastName}" />
         <TextBlock Text="Given name:" />
         <TextBox Text="{Binding GivenName}" />
         <TextBlock Text="E-Mail:" />
         <TextBox Text="{Binding MailAddress}" />
 
         <!-- 我们无法在编译绑定中绑定到方法,所以使用ReflectionBinding -->
         <Button Content="Send an E-Mail"
                 Command="{ReflectionBinding SendEmailCommand}" />
     </StackPanel>
 </UserControl>


已知限制

编译绑定有一些已知的限制:

  • 编译绑定无法绑定到通过名字指定的元素

  • 编译绑定无法在样式中通过RelativeResource绑定到TemplatedParent(例如:{Binding Width, RelativeSource={RelativeSource TemplatedParent}})

如果你遇到了上述的限制,你需要禁用编译绑定或使用ReflectionBinding

总结:开启,可以检查自己绑定的属性或者对象是否正确,并能提升性能。但是需要注意特殊场景被限制

Avalonia对汉字的显示不够友好

以下样式是对全局的textbox的汉字进行设置可以正常显示,其他的控件也可参照此例

 <Window.Styles>
    <Style Selector="TextBox" >
       <Setter Property="FontFamily" Value="宋体,Simsun,微软雅黑,Microsoft YaHei,苹方-简,宋体-简">
       </Setter>
    </Style>
 </Window.Styles>

以下是正常运行的结果:

参考博客:https://hedaozi.com/technology/font-in-avalonia/

与控件绑定

绑定到已命名控件

如果要绑定到另一个已命名控件的属性,可以使用以#字符为前缀的控件名称。

 <TextBox Name="other">
 
 <!-- 绑定到命名为“other”控件的Text属性 -->
 
 <TextBlock Text="{Binding #other.Text}"/>

这相当于WPF和UWP开发者熟悉的长格式绑定:

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

这两种语法Avalonia均支持,但缩写#语法显得不那么冗长。

绑定到父控件或者父控件的父控件

您可以使用$parent符号绑定到目标在逻辑上的父级:

 <Border Tag="Hello World!">
 
   <TextBlock Text="{Binding $parent.Tag}"/>
 
 </Border>

也可以通过在$parent符号添加索引器绑定到父控件的父控件:

 <Border Tag="Hello World!">
   <Border>
     <TextBlock Text="{Binding $parent[1].Tag}"/>
   </Border>
 </Border>

索引器从0开始,因此$parent[0]等同于$parent

还可以按类型绑定到祖先:

 <Border Tag="Hello World!">
   <Decorator>
   <TextBlock Text="{Binding $parent[Border].Tag}"/>
   </Decorator>
 </Border>

最后,您可以组合索引器和类型:

 <Border Tag="Hello World!">
   <Border>
   <Decorator>
   <TextBlock Text="{Binding $parent[Border;1].Tag}"/>
   </Decorator>
   </Border>
 </Border>

如果需要在祖先类型中包含XAML命名空间,一般使用:字符:

 <local:MyControl Tag="Hello World!">
   <Decorator>
 •    <TextBlock Text="{Binding $parent[local:MyControl].Tag}"/>
   </Decorator>
 </local:MyControl>





Avalonia学习的评论 (共 条)

分享到微博请遵守国家法律