1、XAML
(1)Style样式

  Avalonnia中的样式Stylecss,样式不像在WPF中存储在Resources集合中,而是存储在一个独立的Styles集合中。控件模板ControlThere除外。示例代码如下:

<UserControl>
    <UserControl.Styles>
        <!-- 让带有 h1 样式类的 TextBlock 具有 24 点的字体大小 -->
        <Style Selector="TextBlock.h1">
            <Setter Property="FontSize" Value="24"/>
        </Style>
    </UserControl.Styles>
    <TextBlock Classes="h1">Header</TextBlock>
<UserControl>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
(2)Data Templates数据模版

  在Avalonia UI中,数据模板不会存储在应用程序资源中。相反,数据模板要么放置在控件的DataTemplates集合内,要么放置在Application上。示例如下:

<UserControl xmlns:viewmodels="using:MyApp.ViewModels"
             x:DataType="viewmodels:ControlViewModel">
    <UserControl.DataTemplates>
        <DataTemplate DataType="viewmodels:FooViewModel">
            <Border Background="Red" CornerRadius="8">
                <TextBox Text="{Binding Name}"/>
            </Border>
        </DataTemplate>
    </UserControl.DataTemplates>
    <!-- 假设ControlViewModel.Foo是MyApp.ViewModels.FooViewModel类型的对象,
         则此处将显示一个具有圆角半径为8的红色边框,其中包含一个TextBox。
         只有在使用编译绑定时才需要DataType,因此可以对其类型检查。  -->
    <ContentControl Content="{Binding Foo}"/>
<UserControl>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
(3)Data Template Selector数据模板选择器

  在WPF中,您可以创建DataTemplateSelector来根据提供的数据选择或创建DataTemplate。在Avalonia中,您不能这样做,但是您可以实现IDataTemplate,它可以被看作是DataTemplateSelector的替代品。示例地址: https://docs.avaloniaui.net/zh-Hans/docs/get-started/wpf/datatemplates

(4)WPF的HierarchicalDataTemplate

  在WPF中的HierarchicalDataTemplate在Avalonia中被称为TreeDataTemplate(因为前者难以输入!)

(5)控件基类TemplatedControlControl

  WPF中的UIElementFrameworkElement是非模板控件的基类,大致对应于Avalonia中的Control类。而WPF中的Control类则是一个模板控件,Avalonia中相应的类是TemplatedControl

  • 在WPF/UWP中,您将从Control类继承来创建新的模板控件,而在Avalonia中,您应该从TemplatedControl继承。
  • 在WPF/UWP中,您将从FrameworkElement类继承来创建新的自定义绘制控件,而在Avalonia中,您应该从Control继承。

  因此,简要总结如下:

  • UIElement 🠞 Control
  • FrameworkElement🠞 Control
  • Control 🠞 TemplatedControl
(6)WPF的DependencyProperty

  Avalonia中与DependencyProperty相对应的是StyledProperty,然而Avalonia的属性系统 比WPF更丰富,还包括DirectProperty用于将标准CLR属性转换为Avalonia属性。StyledPropertyDirectProperty的共同基类是AvaloniaProperty

(7)更简易的Grid

  在Avalonia中,可以使用字符串来指定列和行定义,避免了WPF中笨重的语法:<Grid ColumnDefinitions="Auto,*,32" RowDefinitions="*,Auto">。在WPF中,Grid的一个常见用法是将两个控件堆叠在一起。在Avalonia中,为此,您可以直接使用Panel,它比Grid更轻量级。

(8)Tunnelling Events
Avalonia确实有事件隧道传播,但它们不是通过单独的Preview CLR事件处理程序公开的。要订阅一个事件隧道传播事件,您需要使用AddHandler方法,并传递RoutingStrategies.Tunnel参数:

target.AddHandler(InputElement.KeyDownEvent, OnPreviewKeyDown, RoutingStrategies.Tunnel);

void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
    // 处理程序代码
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
(9)EventManager.RegisterClassHandler变化
// WPF
static MyControl()
{
    EventManager.RegisterClassHandler(typeof(MyControl), MyEvent, HandleMyEvent));
}

private static void HandleMyEvent(object sender, RoutedEventArgs e)
{
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
// Avalonia
static MyControl()
{
    MyEvent.AddClassHandler<MyControl>((x, e) => x.HandleMyEvent(e));
}

private void HandleMyEvent(RoutedEventArgs e)
{
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

  请注意,在WPF中,您必须将类处理程序添加为静态方法,而在Avalonia中,类处理程序不是静态的:通知会自动定向到正确的实例。在这种情况下,事件处理程序通常的sender参数是不必要的,一切保持强类型。

(10)PropertyChangedCallback

  在WPF中,监听DependencyProperties的变化可能会变得复杂。当您注册一个DependencyProperty时,可以提供一个静态的PropertyChangedCallback,但如果您想从其他地方监听属性变化, 事情可能会变得复杂和容易出错

  在Avalonia中,注册时没有PropertyChangedCallback,而是在控件的静态构造函数中添加了一个类监听器,方式与 添加事件类监听器的方式非常相似

(11)RenderTransforms 和 RenderTransformOrigin

  在WPF和Avalonia中,RenderTransformOrigin是不同的:如果应用了RenderTransform,请注意Avalonia中RenderTransformOrigin的默认值是RelativePoint.Center,而在WPF中默认值是RelativePoint.TopLeft(0, 0)。在像Viewbox这样的控件中,相同的代码将导致不同的渲染行为:

.Net-Avalonia学习笔记(三)-从WPF转移到Avalonia的注意事项_控件

.Net-Avalonia学习笔记(三)-从WPF转移到Avalonia的注意事项_控件_02

作者:꧁执笔小白꧂