单击通过依赖属性中的命令执行代码的用户控件上的按钮后,我的 WinUI 3 应用程序偶尔会崩溃

问题描述 投票:0回答:1

我有一个 winui 3 项目,在微软的 MVVM 工具包的帮助下使用 MVVM 模式。 我创建了一个具有 2 个 ICommand 类型的 DependencyProperties 的 UserControl。这样,当我在视图中使用此控件时,我可以执行视图模型中按钮单击的代码,以符合 mvvm 原则。

用户控制:

 public sealed partial class MyDialog : UserControl
 {
     public static readonly DependencyProperty YesSelectedCommandProperty = 
         DependencyProperty.Register("YesSlectedCommand", typeof(ICommand), typeof(AddinAutoAttachDialog), new PropertyMetadata(null, OnYesCommandChanged));

     public static readonly DependencyProperty NoSelectedCommandProperty =
         DependencyProperty.Register("NoSelectedCommand", typeof(ICommand), typeof(AddinAutoAttachDialog), new PropertyMetadata(null, OnNoCommandChanged));

     public ICommand YesSlectedCommand
     {
         get { return (ICommand)GetValue(YesSelectedCommandProperty); }
         set { SetValue(YesSelectedCommandProperty, value); }
     }

     public ICommand NoSlectedCommand
     {
         get { return (ICommand)GetValue(NoSelectedCommandProperty); }
         set { SetValue(NoSelectedCommandProperty, value); }
     }
     public MyDialog()
     {
         this.InitializeComponent();
     }

对应的xaml代码:

  <Button Content="Yes"
          Command="{x:Bind YesSlectedCommand, Mode=OneTime}"/>

  <Button Content="No"
          Command="{x:Bind NoSlectedCommand, Mode=OneTime}" />

我认为这样使用它:

<components:MyDialog Visibility="{x:Bind MainViewModel.ShowMyDialog, Mode=OneWay}"
    YesSlectedCommand="{x:Bind MainViewModel.YesSelected, Mode=OneWay}"
    NoSlectedCommand="{x:Bind MainViewModel.NoSelected, Mode=OneWay}" />
<InfoBar IsOpen="True"
         Severity="Success"
         Title="..." 
         Visibility="{x:Bind MainViewModel.ShowSuccessInfoBar, Mode=OneWay}"/>

<InfoBar IsOpen="True"
         Severity="Error"
         Title="..."
         Visibility="{x:Bind MainViewModel.ShowErrorInfoBar, Mode=OneWay}" />

然后在我的视图模型中执行类似的代码(主要是更改 UI 元素的可见性):

internal partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    private bool showMyDialog = false;

    [ObservableProperty]
    private bool showSuccessInfoBar = false;

    [ObservableProperty]
    private bool showErrorInfoBar = false;

    [RelayCommand]
    private void YesSelected()
    {
        bool succeeded = ExecuteSomeOperations();
        ShowMyDialog = false;
        ShowSuccessInfoBar = succeeded;
        ShowErrorInfoBar = !succeeded;
    }

    [RelayCommand]
    private void NoSelected()
    {
        ShowMyDialog = false;
        ShowErrorInfoBar = true;
    }
}

奇怪的是,当我选择“否”按钮或有时选择“是”按钮时,我的应用程序有时会崩溃。但其他时候它会正确显示所有内容。

当我连接调试器时,我唯一看到的是这行消息: 程序“[9964] MyWindow.exe”已退出,代码为 3221226107 (0xc000027b)。 我检查了事件查看器,发现了这个:

Faulting application name: MyWindow.exe, version: 1.0.0.0, time stamp: 0x661f0000
Faulting module name: Microsoft.ui.xaml.dll, version: 3.1.4.0, time stamp: 0x343afd70
Exception code: 0xc000027b
Fault offset: 0x00000000003b9584
Faulting process id: 0x0x4930
Faulting application start time: 0x0x1DAFE12C2C9EF06
Faulting module path: \...\Microsoft.ui.xaml.dll
Faulting package full name: 
Faulting package-relative application ID: 

我尝试将其包装在 try catch 块中,但没有捕获到任何异常,并且在 Yes/NoSelected 方法中修改 UI 元素可见性的命令中的代码可以成功执行。我还尝试查找绑定失败,因为当我修改 UI 时它似乎崩溃了。 (顺便说一句,我不会从另一个线程修改 UI)所以我也尝试了这个:

public App()
{
    this.InitializeComponent();

    this.DebugSettings.BindingFailed += (s, e) =>
    {
        File.AppendAllText(LogPath, $"BindingFailed: {e.Message}");
    };
}

但是我的日志文件中没有关于绑定失败的日志。

这里可能出现什么问题?

c# xaml mvvm winui-3 winui
1个回答
0
投票

问题出在数据绑定上。我忘记使用布尔值到可见性转换器来实现控件的可见性。但就我而言,根元素在我看来是一个窗口,无法将 x:bind 与转换器一起使用,因此我必须切换到绑定标记扩展。由于 x:bind 和 Binding 的数据上下文不同,我必须使用设置它的容器网格中的数据上下文。

所以我修改了代码:

<InfoBar IsOpen="True"
         Severity="Success"
         Title="..." 
         Visibility="{x:Bind MainViewModel.ShowSuccessInfoBar, Mode=OneWay}"/>

对此:

<InfoBar IsOpen="True"
         Severity="Success"
         Title="..."
         Visibility="{Binding ElementName=myGrid, Path=DataContext.ShowSuccessInfoBar, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}" />

它解决了偶发的崩溃问题,但我仍然不明白为什么首先可以工作,因为有时它可以正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.