WinUI 3 應用程式異常狀況處理

WinUI 3 應用程式異常狀況處理

此 WinUI 3 應用程式在偵錯模式下執行一切正常,但發行組建版本卻會發生當機,錯誤訊息如下所示。

一般開發過程中,我很少遇到這類詭異問題。WinUI 3 多半只會拋出內部執行階段例外,難以從例外堆疊中找到有效的除錯線索。

經過多輪逐一測試排除後,我追查出當機原因是頁面初始化檢視模型時觸發了參考空值例外。以下是專案架構:主視窗搭配側邊導覽選單,點擊選單項目就會在右側主要內容區載入對應頁面。主視窗使用的 XAML 程式碼片段如下:

<TabView Name="tabView" IsAddTabButtonVisible="False" Margin="10" VerticalAlignment="Stretch" TabCloseRequested="TabView_TabCloseRequested">
    <TabViewItem x:Uid="tabConsonant" Name="tvHome">
    </TabViewItem>
</TabView>Code language: HTML, XML (xml)

這個分頁檢視元件負責在右側載入內容頁面,我在後端程式碼中將目標頁面執行個體指派給 tvHome:

private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
{
    tvHome.Content = new ConsonantsPage();
}Code language: JavaScript (javascript)

進一步除錯後確認,程式正好執行到目標頁面內 this.DataContext = vm; 這一行時就會當機。

之後我測試了一個全新空白頁面,該頁面完全未設定內容環境與資料繫結,載入時完全沒有出現任何錯誤。由此可確認,問題根源肯定與 XAML 資料繫結邏輯有關。我不再使用標準 MVVM 繫結方式,改為直接在後置程式碼裡動態建立介面元件做為權宜解法。

最終有效修正方案:

所有介面控制項建立與數值繫結,全部透過 C# 後端程式實作:

 public TonePage()
        {
            InitializeComponent();
            Loaded += Page_Loaded;
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            var toneData = ThaiAlphabetSource.Tones;
            FillToneGrid(gvToneList, toneData);
        }

        private void FillToneGrid(GridView grid, List<ToneInfo> source)
        {
            foreach (var item in source)
            {
                Button btnRoot = new Button
                {
                    HorizontalContentAlignment = HorizontalAlignment.Center,
                    VerticalContentAlignment = VerticalAlignment.Center,
                    Tag = item.Audio
                };
                btnRoot.Click += PlayClick;

                StackPanel sp = new StackPanel
                {
                    Width = 240,
                    Orientation = Orientation.Vertical,
                    HorizontalAlignment = HorizontalAlignment.Center,
                    VerticalAlignment = VerticalAlignment.Center
                };

                TextBlock tbTitle = new TextBlock
                {
                    HorizontalAlignment = HorizontalAlignment.Center,
                    FontSize = 50,
                    Foreground = new SolidColorBrush(Color.FromArgb(0xFF, 0x01, 0xA0, 0xC7)),
                    Text = item.Letter_Title
                };
                TextBlock tbName = new TextBlock
                {
                    HorizontalAlignment = HorizontalAlignment.Center,
                    FontSize = 30,
                    Text = item.Letter_Name
                };
                TextBlock tbScript = new TextBlock
                {
                    HorizontalAlignment = HorizontalAlignment.Center,
                    FontSize = 30,
                    Text = item.Letter_Script
                };

                sp.Children.Add(tbTitle);
                sp.Children.Add(tbName);
                sp.Children.Add(tbScript);
                btnRoot.Content = sp;

                grid.Items.Add(btnRoot);
            }
        }Code language: PHP (php)

我並沒有深入追查底層確切的程式錯誤,但推測問題是來自 Command="{Binding PlayCommand}" 這類命令繫結語法。另一項測試結果也佐證了這個推論:僅使用一般屬性繫結、完全沒有命令繫結的頁面,在發行版本中都能正常執行,範例如下:

<Button Content="{Binding}" Grid.Row="0" Grid.Column="1" BorderBrush="#ccc" Foreground="Black" FontSize="50" Height="100" Width="130" Click="Button_Click"/>Code language: HTML, XML (xml)

這種寫法在發行組態下執行完全正常。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *