WinUI 3应用点击自定义控件按钮后偶发崩溃问题排查
可能的崩溃原因及修复方案
1. 依赖属性注册的目标类型错误
你的MyDialog类中,注册依赖属性时错误地使用typeof(AddinAutoAttachDialog)作为目标类型,实际类名应为MyDialog。WinUI依赖属性系统对类型匹配要求严格,这种不匹配会触发内部XAML解析异常,导致崩溃。
错误代码:
public static readonly DependencyProperty YesSelectedCommandProperty = DependencyProperty.Register("YesSlectedCommand", typeof(ICommand), typeof(AddinAutoAttachDialog), new PropertyMetadata(null, OnYesCommandChanged));
修复后:
public static readonly DependencyProperty YesSelectedCommandProperty = DependencyProperty.Register("YesSelectedCommand", typeof(ICommand), typeof(MyDialog), new PropertyMetadata(null, OnYesCommandChanged));
2. 属性名拼写不一致(Selected拼写错误)
代码中多处存在拼写错误:
- 依赖属性注册名写成
YesSlectedCommand(少字母e,正确应为YesSelectedCommand) - UserControl的CLR属性、XAML绑定均使用错误拼写,而ViewModel中
[RelayCommand]自动生成的命令属性是YesSelectedCommand(正确拼写)
这种不匹配会导致绑定失效,触发WinUI内部命令执行异常。
修复步骤:
统一所有属性名为YesSelectedCommand和NoSelectedCommand:
// 依赖属性注册 public static readonly DependencyProperty YesSelectedCommandProperty = DependencyProperty.Register("YesSelectedCommand", typeof(ICommand), typeof(MyDialog), new PropertyMetadata(null, OnYesCommandChanged)); public static readonly DependencyProperty NoSelectedCommandProperty = DependencyProperty.Register("NoSelectedCommand", typeof(ICommand), typeof(MyDialog), new PropertyMetadata(null, OnNoCommandChanged)); // CLR属性 public ICommand YesSelectedCommand { get { return (ICommand)GetValue(YesSelectedCommandProperty); } set { SetValue(YesSelectedCommandProperty, value); } } public ICommand NoSelectedCommand { get { return (ICommand)GetValue(NoSelectedCommandProperty); } set { SetValue(NoSelectedCommandProperty, value); } }
修正UserControl的XAML绑定:
<Button Content="Yes" Command="{x:Bind YesSelectedCommand, Mode=OneTime}"/> <Button Content="No" Command="{x:Bind NoSelectedCommand, Mode=OneTime}" />
修正View中的绑定:
<components:MyDialog Visibility="{x:Bind MainViewModel.ShowMyDialog, Mode=OneWay}" YesSelectedCommand="{x:Bind MainViewModel.YesSelectedCommand, Mode=OneWay}" NoSelectedCommand="{x:Bind MainViewModel.NoSelectedCommand, Mode=OneWay}" />
3. InfoBar同时使用IsOpen和Visibility导致冲突
你给InfoBar同时设置IsOpen="True"和绑定Visibility,两个属性都会控制显示状态,WinUI内部处理这种矛盾状态时可能引发布局异常。
修复方案:
只保留一种控制逻辑,推荐使用IsOpen(符合InfoBar设计意图):
<InfoBar Severity="Success" Title="..." IsOpen="{x:Bind MainViewModel.ShowSuccessInfoBar, Mode=OneWay}"/> <InfoBar Severity="Error" Title="..." IsOpen="{x:Bind MainViewModel.ShowErrorInfoBar, Mode=OneWay}" />
4. 未实现依赖属性的回调方法
你在依赖属性注册时指定了OnYesCommandChanged和OnNoCommandChanged回调,但未实现这些方法。虽然编译不会报错,但WinUI触发回调时会找不到方法,引发内部异常。
修复方案:
如果不需要回调,直接将PropertyMetadata的回调参数设为null;如果需要回调,实现对应方法:
// 不需要回调的情况 public static readonly DependencyProperty YesSelectedCommandProperty = DependencyProperty.Register("YesSelectedCommand", typeof(ICommand), typeof(MyDialog), new PropertyMetadata(null)); // 实现回调方法的情况 private static void OnYesCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // 添加自定义逻辑 }
5. UI线程访问问题(潜在风险)
如果ExecuteSomeOperations是异步或耗时操作,直接在命令中修改UI属性可能导致线程访问错误,引发偶发崩溃。
修复方案:
确保在UI线程修改属性:
[RelayCommand] private async void YesSelected() { bool succeeded = await Task.Run(() => ExecuteSomeOperations()); await DispatcherQueue.EnqueueAsync(() => { ShowMyDialog = false; ShowSuccessInfoBar = succeeded; ShowErrorInfoBar = !succeeded; }); }
内容的提问来源于stack exchange,提问作者Rena821
相关产品推荐
相关产品推荐

