You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Avalonia按钮点击切换图片崩溃问题排查与解决求助

Avalonia UI扑克牌按钮图片切换崩溃问题排查与解决

我在Avalonia UI应用中创建了一个扑克牌按钮网格,每个按钮关联一张扑克牌图片,期望点击按钮时,对应卡片图片切换为另一张图片以实现“刷新”效果。但实现代码后应用出现崩溃,无法达成平滑切换的需求,附上相关XAML与C#代码,请求指导排查并解决该问题。

XAML代码

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:AvaloniaApplication2.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" Width="320" d:DesignWidth="320" d:DesignHeight="450"
        x:Class="AvaloniaApplication2.Views.MainWindow"
        x:DataType="vm:MainWindowViewModel"
        Icon="/Assets/avalonia-logo.ico"
        Title="AvaloniaApplication2">

    <Design.DataContext>
        <!-- This only sets the DataContext for the previewer in an IDE,
             to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
        <vm:MainWindowViewModel/>
    </Design.DataContext>

    <Grid Name="Grid">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        
        <Button Click="Button_OnClick">
            <Image Name="Button1Image" Source="/Assets/Images/c9.png" />
        </Button>
        
        <Button Grid.Row="1">
            <Image Source="/Assets/Images/крести_10.png" />
        </Button>

        <Button Grid.Row="2">
            <Image Source="/Assets/Images/крести_j.png" />
        </Button>
        
        <Button Grid.Row="3">
            <Image Source="/Assets/Images/крести_q.png" />
        </Button>
                
        <Button Grid.Row="4">
            <Image Source="/Assets/Images/крести_k.png" />
        </Button>
        
        <Button Grid.Row="5">
            <Image Source="/Assets/Images/крести_а.png" />
        </Button>
        
        <Button Grid.Row="0" Grid.Column="1">
            <Image Source="/Assets/Images/буби_9.png" />
        </Button>
        
        <Button Grid.Row="1" Grid.Column="1">
            <Image Source="/Assets/Images/буби_10.png" />
        </Button>
        
        <Button Grid.Row="2" Grid.Column="1">
            <Image Source="/Assets/Images/буби_j.png" />
        </Button>
        
        <Button Grid.Row="3" Grid.Column="1">
            <Image Source="/Assets/Images/буби_q.png" />
        </Button>
        
        <Button Grid.Row="4" Grid.Column="1">
            <Image Source="/Assets/Images/буби_k.png" />
        </Button>
        
        <Button Grid.Row="5" Grid.Column="1">
            <Image Source="/Assets/Images/буби_а.png" />
        </Button>
        
        <Button Grid.Row="0" Grid.Column="2">
            <Image Source="/Assets/Images/чирви_9.png" />
        </Button>
        
        <Button Grid.Row="1" Grid.Column="2">
            <Image Source="/Assets/Images/чирви_10.png" />
        </Button>
        
        <Button Grid.Row="2" Grid.Column="2">
            <Image Source="/Assets/Images/чирви_j.png" />
        </Button>
        
        <Button Grid.Row="3" Grid.Column="2">
            <Image Source="/Assets/Images/чирви_q.png" />
        </Button>
        
        <Button Grid.Row="4" Grid.Column="2">
            <Image Source="/Assets/Images/чирви_k.png" />
        </Button>
        
        <Button Grid.Row="5" Grid.Column="2">
            <Image Source="/Assets/Images/чирви_а.png" />
        </Button>
        
        <Button Grid.Row="0" Grid.Column="3">
            <Image Source="/Assets/Images/пики_9.png" />
        </Button>
        
        <Button Grid.Row="1" Grid.Column="3">
            <Image Source="/Assets/Images/пики_10.png" />
        </Button>
        
        <Button Grid.Row="2" Grid.Column="3">
            <Image Source="/Assets/Images/пики_j.png" />
        </Button>
        
        <Button Grid.Row="3" Grid.Column="3">
            <Image Source="/Assets/Images/пики_q.png" />
        </Button>
        
        <Button Grid.Row="4" Grid.Column="3">
            <Image Source="/Assets/Images/пики_k.png" />
        </Button>
        
        <Button Grid.Row="5" Grid.Column="3">
            <Image Source="/Assets/Images/пики_а.png" />
        </Button>
        
    </Grid>

</Window>

C#代码

using System.Linq;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;

namespace AvaloniaApplication2.Views;

public partial class MainWindow : Window
{
    private Image _button1Image;
    public MainWindow()
    {
        InitializeComponent();
    }
    
    private void InitializeComponent()
    {
        AvaloniaXamlLoader.Load(this);
        _button1Image = this.FindControl<Image>("Button1Image");
    }


    private void Button_OnClick(object? sender, RoutedEventArgs e)
    {
        _button1Image.Source = new Bitmap("/Assets/Images/reload.png"); 
    }
}

问题排查

崩溃的核心原因有三点:

  • 资源加载方式错误:直接用本地文件路径创建Bitmap,Avalonia运行时无法正确识别打包后的资源路径,导致文件找不到异常。
  • 空值未校验:_button1Image可能因控件查找失败为null,触发NullReferenceException。
  • 图片资源配置错误:图片文件未设置正确的生成操作,运行时无法读取。

解决方案

1. 修正图片资源的生成操作

右键项目中/Assets/Images下的所有图片文件,设置生成操作为Resource(推荐)或Content,确保运行时能正确访问。

2. 改用Avalonia资源协议加载图片

替换点击事件中的Bitmap创建方式,使用Avalonia专属的avares://资源协议:

private void Button_OnClick(object? sender, RoutedEventArgs e)
{
    if (_button1Image == null) return; // 增加空值校验,避免空引用崩溃
    
    // 格式:avares://[程序集名称]/[资源路径],替换为你的项目名称
    _button1Image.Source = new Bitmap(new Uri("avares://AvaloniaApplication2/Assets/Images/reload.png"));
}

3. 优化控件查找(Avalonia 11+)

使用Avalonia自动生成的分部类控件引用,避免手动查找出错:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_OnClick(object? sender, RoutedEventArgs e)
    {
        if (Button1Image == null) return;
        Button1Image.Source = new Bitmap(new Uri("avares://AvaloniaApplication2/Assets/Images/reload.png"));
    }
}

4. 实现平滑切换效果

如果需要图片切换时的过渡动画,可改用TransitioningContentControl包裹图片:
修改XAML按钮内容:

<Button Click="Button_OnClick">
    <TransitioningContentControl Name="Button1Content" Transition="CrossFade">
        <Image Source="/Assets/Images/c9.png" />
    </TransitioningContentControl>
</Button>

修改点击事件代码:

private void Button_OnClick(object? sender, RoutedEventArgs e)
{
    if (Button1Content == null) return;
    Button1Content.Content = new Image { Source = new Bitmap(new Uri("avares://AvaloniaApplication2/Assets/Images/reload.png")) };
}

内容的提问来源于stack exchange,提问作者Julia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 20:00:52