浅谈avalonia与WPF的区别(一)

官网

什么是 Avalonia? | Avalonia Docs

底层架构区别

Avalonia:

WPF:

对比维度WPFAvalonia
平台支持与依赖Windows系统,深度集成DirectX渲染和Win32 API,仅支持Windows平台基于.NET Standard 2.0,通过抽象层兼容多平台(Windows/Linux/macOS/iOS/Android),使用Skia渲染引擎实现跨平台一致性
渲染引擎DirectX (Windows独占)Skia
样式系统基于ResourceDictionaryStyle对象,通过BasedOn继承样式样式选择器+伪类 ControlTheme定义基础主题,Style覆盖具体场景
数据绑定强依赖ICommand支持直接绑定方法(无需ICommand包装),保留ICommand用于高级场景(如CanExecute
字体系统字体嵌入字体(如思源黑体)以避免跨平台显示异常

实现细节区别

1.ControlTheme和Style的区别

Avalonia :样式通常定义在 Window.Styles 或全局资源字典中。Avalonia 使用 Selector 属性来指定样式将应用于哪些控件。 控件主题是在样式的基础上构建的,用于为控件创建可切换的主题。ControlTheme类似于WPF的Style,通常用于为无外观的控件创建主题。

<Application xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="AvaloniaApplication.App">
  <Application.Styles>
    <FluentTheme/>
  </Application.Styles>

  <Application.Resources>
    <!-- 自定义按钮样式 -->
    <ControlTheme x:Key="RoundedButtonTheme" TargetType="Button">
      <Setter Property="Background" Value="#4CAF50"/> <!-- 绿色背景 -->
      <Setter Property="Foreground" Value="White"/>
      <Setter Property="Padding" Value="12,6"/>
      <Setter Property="BorderBrush" Value="#388E3C"/>
      <Setter Property="BorderThickness" Value="2"/>
      <Setter Property="Template">
        <ControlTemplate>
          ...
        </ControlTemplate>
      </Setter>
    </ControlTheme>
  </Application.Resources>
</Application>

在选择步骤中,样式系统从控件开始沿着逻辑树向上搜索。这意味着在应用程序的最高级别(例如 App.axaml 文件)定义的样式可以在应用程序的任何地方使用,但仍然可以在控件更近的地方(例如在窗口或用户控件中)进行覆盖。

WPF : 通常在Window.Resources。在 WPF 中是通过 TargetType 实现的。

<Window.Resources>  
    <Style x:Key="MyButtonStyle" TargetType="Button">  
        <Setter Property="Background" Value="LightBlue"/>  
        <Setter Property="Foreground" Value="White"/>  
        <Setter Property="FontSize" Value="16"/>  
        <Setter Property="Template">  
            <Setter.Value>  
                <ControlTemplate TargetType="Button">  
                    <Border Background="{TemplateBinding Background}"  
                            BorderBrush="Black"  
                            BorderThickness="1">  
                        <ContentPresenter HorizontalAlignment="Center"  
                                          VerticalAlignment="Center"/>  
                    </Border>  
                </ControlTemplate>  
            </Setter.Value>  
        </Setter>  
    </Style>  
</Window.Resources>  
  
<Button Style="{StaticResource MyButtonStyle}" Content="Click Me"/>
2.依赖属性 

WPF:DependencyProperty 

  public static readonly DependencyProperty ContentProperty =
  DependencyProperty.Register("Content", typeof(string), typeof(AduCheckComboBox), new             PropertyMetadata(string.Empty));
  /// <summary>
  /// 内容
  /// </summary>
  public string Content
  {
     get { return (string)GetValue(ContentProperty); }
     set { SetValue(ContentProperty, value); }
  }

Avalonia: 

  • 若属性需要被样式系统或控件模板影响和扩展,那么推荐使用StyledProperty
  • AvaloniaProperty则更适合那些不需要与样式直接交互,或者不需要继承性质的一般依赖属性。
//方法一:
public class MyControl : Avalonia.Controls.Control
{
    public static readonly StyledProperty<int> MyPropertyProperty =
        AvaloniaProperty.Register<MyControl, int>(nameof(MyProperty), defaultValue: 0, onChanged: OnMyPropertyChanged);

    public int MyProperty
    {
        get { return GetValue(MyPropertyProperty); }
        set { SetValue(MyPropertyProperty, value); }
    }

    private static void OnMyPropertyChanged(AvaloniaPropertyChangedEventArgs e)
    {
        MyControl control = e.Sender as MyControl;
        int newValue = (int)e.NewValue;

        // Add your class handler logic here
        // For example:
        control.Classes.Set("my-class", newValue > 0);
    }
}

//方法二
public MyControl()
    {
        MyPropertyProperty.Changed.AddClassHandler<MyControl>(MyPropertyPropertyChangedCallBack);
    }
3.非模板控件的基类
WPFAvalonia
非模板控件的基类UIElementControl
非模板控件的基类(自定义绘制控件)FrameworkElementControl
控件ControlTemplatedControl
依赖属性DependencyPropertyStyledProperty

4.Grid写法

WPF:

<Grid>  
    <!-- 定义列 -->  
    <Grid.ColumnDefinitions>  
        <!-- 第一列自动调整大小以适应内容 -->  
        <ColumnDefinition Width="Auto" />  
        <!-- 第二列使用剩余空间 -->  
        <ColumnDefinition Width="*" />  
        <!-- 第三列固定宽度为32 -->  
        <ColumnDefinition Width="32" />  
    </Grid.ColumnDefinitions>  
  
    <!-- 定义行 -->  
    <Grid.RowDefinitions>  
        <!-- 第一行使用剩余空间 -->  
        <RowDefinition Height="*" />  
        <!-- 第二行自动调整大小以适应内容 -->  
        <RowDefinition Height="Auto" />  
    </Grid.RowDefinitions>  
  </Grid>

Avalonia:

<Grid ColumnDefinitions="Auto,*,32" RowDefinitions="*,Auto">
5.隧道(也称为预览)事件 

隧道(也称为预览)事件首先在最顶层的元素上触发,然后逐级向下传播到事件的原始源。这与冒泡事件相反,冒泡事件从事件的原始源开始,然后向上传播到包含它的元素。

WPF:通过单独的Preview CLR事件处理程序公开的

示例:将使用PreviewKeyDown事件,这是一个隧道事件,用于在键盘按键被按下时触发

若你在某个事件处理程序中设置了e.Handled = true;(如注释所示),则事件将不会继续传播到更下层的元素。这可以用于在事件到达其原始源之前拦截并处理事件。

private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)  
        {  
            MessageBox.Show("TextBox PreviewKeyDown: " + e.Key.ToString());  
  
            // 可以在这里处理键盘输入,或者通过设置e.Handled = true来阻止事件进一步传播  
            // e.Handled = true;  
        }  

 Avalonia::要订阅一个事件隧道传播事件,您需要使用AddHandler方法,并传递RoutingStrategies.Tunnel参数:

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

void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
    // 处理程序代码
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值