Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid 0xc000027b Application Crash when no DataTemplate is provided for ItemsSource Bindings in SettingsExpander #191

Open
RobertK66 opened this issue Aug 28, 2023 · 14 comments
Labels
documentation Improvements or additions to documentation

Comments

@RobertK66
Copy link

Not sure if this was discussed already somewhere else ...
But (now) I use the prerelease v8.0.230823-rc of this repository (Same issue occurred with last 'experimental' version 0.0.18 from the 'CommunityToolkit.Labs' package).

When binding an ObservableCollection to the ItemsSource attribute of a SettingsExpander, everything works as expected - when started from VisualStudio IDE.

However, when I start the installed App from Windows Start Menu the Application crashes with the first click on the Expander. The Windows Event Logger shows Application Error code 0xc000027b.

WinUi3AppError

Steps to reproduce:

I am using Visual Studio 2022 Version 17.7.2 with AppSdk and Build Tools installed. Made a fresh Solution with "WinUI 3 Desctop - packaged" - Template.

My XAML:

<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="WinUi3Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinUi3Test"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:labs="using:CommunityToolkit.WinUI.Controls"
    mc:Ignorable="d">

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">

        <labs:SettingsExpander Header="My String List" HeaderIcon="PreviewLink" ItemsSource="{x:Bind MyList, Mode=TwoWay}"  MinWidth="200">
        </labs:SettingsExpander>

        <Button Content="ADD" Click="Button_Click" />
        <Button Content="CLR" Click="Button_Click_1" />

    </StackPanel>
</Window>

My Code behind:

namespace WinUi3Test {
    /// <summary>
    /// An empty window that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainWindow : Window, INotifyPropertyChanged {

        private ObservableCollection<String> _mylist = new() { "first", "second" };
        public ObservableCollection<String> MyList { get => _mylist; set => SetProperty( ref _mylist, value); }


        public MainWindow() {
            this.InitializeComponent();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private bool SetProperty<T>([NotNullIfNotNull(nameof(newValue))] ref T field, T newValue, [CallerMemberName] string propertyName = null) {
            if (EqualityComparer<T>.Default.Equals(field, newValue)) {
                return false;
            }
            field = newValue;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            return true;
        }

        private static int i = 0;
        private void Button_Click(object sender, RoutedEventArgs e) {
            MyList.Add("next" + i++);
        }

        private void Button_Click_1(object sender, RoutedEventArgs e) {
            MyList.Clear();
        }
    }
}

My (Test) Project XML:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
    <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
    <RootNamespace>WinUi3Test</RootNamespace>
    <ApplicationManifest>app.manifest</ApplicationManifest>
    <Platforms>x86;x64;ARM64</Platforms>
    <RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
    <PublishProfile>win10-$(Platform).pubxml</PublishProfile>
    <UseWinUI>true</UseWinUI>
    <EnableMsixTooling>true</EnableMsixTooling>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="Assets\SplashScreen.scale-200.png" />
    <Content Include="Assets\LockScreenLogo.scale-200.png" />
    <Content Include="Assets\Square150x150Logo.scale-200.png" />
    <Content Include="Assets\Square44x44Logo.scale-200.png" />
    <Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
    <Content Include="Assets\StoreLogo.png" />
    <Content Include="Assets\Wide310x150Logo.scale-200.png" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.230823-rc" />
    <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.3.230724000" />
    <PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.756" />
    <Manifest Include="$(ApplicationManifest)" />
  </ItemGroup>

  <!-- 
    Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
    Tools extension to be activated for this project even if the Windows App SDK Nuget
    package has not yet been restored.
  -->
  <ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
    <ProjectCapability Include="Msix" />
  </ItemGroup>

  <!-- 
    Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution 
    Explorer "Package and Publish" context menu entry to be enabled for this project even if 
    the Windows App SDK Nuget package has not yet been restored.
  -->
  <PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
    <HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
  </PropertyGroup>
</Project>
@niels9001
Copy link
Collaborator

@RobertK66 Could you try moving the StackPanel and all its content into a Page, and add the Page to the Window? IIRC there might be some WinUI3-related binding quirks when hosting stuff directly in a Window

@RobertK66
Copy link
Author

Ok, I will try. But i think it does not matter because my original problem was happening in a SettingsPage.xaml which was navigated to by MainWindow containing a NavigationView. Shall I also use a separate ViewModel class? I am not sure if using the code behind as the INotifyPropertyChanged implementation is a wise design decision ;-) ...

@RobertK66
Copy link
Author

Moved code into SettingsPage Class and XML StackPanel into the grid proposed by the Empty Page template.
Added Page in Xaml of MainWindow:

  ...
  <local:SettingsPage/>
  ...

Same behaviour:

  • running from IDE-> all works (Adding and deleting rows in the List is shown in both states expanded/collapsed ).
  • running from windows Start -> crash when trying to expand first time.

What's interesting: If I delete the list before clicking the first expand (So the Observable collection is empty) then the empty list opens and no crash! When Adding an Item -> crash!

@RobertK66
Copy link
Author

Next Version, I tried to use a DataContext object with its own Class in the SettingsPage and changed the Binding to
ItemsSource="{Binding Path=MyList, Mode=TwoWay}"

No change. Crashes when started from Windows. Works when started from Visual Studio.

Is there any way I can get more crash info!? ( I did use the 'delayed Start' feature from Visual Studio, Started from Windows Start Menu -> VS Debuger gets attached -> everything works without problems again ....)

@niels9001
Copy link
Collaborator

@RobertK66 just to be sure, could you try adding a DataTemplate like:

And would you mind creating minimal repro (zipped as attachment is fine)?

@RobertK66
Copy link
Author

RobertK66 commented Aug 28, 2023

@RobertK66
Copy link
Author

Tried To use an ItemTemlate. Was not sure how to make a DataBinding to System.String. So I changed my ObservableCollection to have MyLine - Objects as content and used this template:

no change, again it crashes when used without VS!

<?xml version="1.0" encoding="utf-8"?>
<Page
    x:Class="WinUi3Test.SettingsPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinUi3Test"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:labs="using:CommunityToolkit.WinUI.Controls"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:system="using:System"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    

    <Grid>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">

            <labs:SettingsExpander Header="My String List" HeaderIcon="PreviewLink" ItemsSource="{x:Bind MyContext.MyList,  Mode=TwoWay}"  MinWidth="200">
                <labs:SettingsExpander.ItemTemplate>
                    <DataTemplate x:DataType="local:MyLine">
                        <TextBlock Text="{x:Bind TheValue}" >
                        </TextBlock>
                    </DataTemplate>
                </labs:SettingsExpander.ItemTemplate>
            </labs:SettingsExpander>

            <Button Content="ADD" Click="Button_Click" />
            <Button Content="CLR" Click="Button_Click_1" />

        </StackPanel>
    </Grid>
</Page>

@niels9001
Copy link
Collaborator

niels9001 commented Aug 28, 2023

@RobertK66 I just tried this, and it seems to be solving the issue:

<labs:SettingsExpander
     MinWidth="200"
     Header="My String List"
     HeaderIcon="PreviewLink"
     ItemsSource="{Binding Path=MyList, Mode=TwoWay}">
     <labs:SettingsExpander.ItemTemplate>
         <DataTemplate x:DataType="x:String">
             <labs:SettingsCard Description="{Binding}" Header="{Binding}">
                 <HyperlinkButton Content="{Binding}" />
             </labs:SettingsCard>
         </DataTemplate>
     </labs:SettingsExpander.ItemTemplate>
 </labs:SettingsExpander>

Are you seeing the same?

I bet this is because we are doing some things here and the Items are supposed to be of type SettingsCard. So binding directly (string) wouldn't work. The ItemTemplate here adds a SettingsCard first, and binds the string to the Description, Header and HyperlinkButton.Content.

@RobertK66
Copy link
Author

RobertK66 commented Aug 28, 2023

Ok, I didn't catch that there have to be SettingCards only in the Expander !!!

Yes this now removes the crash. But this is not easy to find and debug......

What I also wonder is, Why the hell does it work so 'normaly' in a Debugger hosted environment started from VS!

And Thx. for your fast reply 😄 !

@michael-hawker michael-hawker moved this to 🏗 In progress in Toolkit 8.x Aug 28, 2023
@michael-hawker michael-hawker moved this from 🏗 In progress to 🆕 New in Toolkit 8.x Aug 28, 2023
@michael-hawker michael-hawker added the documentation Improvements or additions to documentation label Aug 28, 2023
@RobertK66
Copy link
Author

RobertK66 commented Aug 29, 2023

May I suggest to add a Default DataTemplate to the SettingsExpander.xaml:

...
<Setter Property="ItemTemplate">
    <Setter.Value>
        <DataTemplate>
            <local:SettingsCard Header="{Binding}" />
        </DataTemplate>
    </Setter.Value>
</Setter>
...

It would change the behavior of my (stupidly) misconfigured Usage of ItemsSource without providing my own DataTemplate. It would fallback to use a simple settings card and (i hope) it will avoid the 0xc000027b Crash.

I removed the SettingsExpander.ItemTemplate from your 'SettingsExpanderItemsSourceSample'. I could not Test the crash behavior. But I could Test the Visual Studio Look of the Example.
Without Default ItemTemplate:
WithOriginalCode

With proposed Change:
WithDefaultDataTemplate

I was not able to test the 'installed behavior' with your component head application. But the look and feel in Visual studio is exactly as I experienced the original issue (seeing the ToString() result of the bound Items objects in some 'sort of list'). Unfortunately testing this proposal for all head environments and creating a pull request is by far out of scope of my developer skills, sorry :-(.

@RobertK66 RobertK66 changed the title SettingsExpander with x:Bind on ItemsSource crashes installed Application Avoid 0xc000027b Application Crash when no DataTemplate is provided for ItemsSource Bindings Aug 29, 2023
@RobertK66 RobertK66 changed the title Avoid 0xc000027b Application Crash when no DataTemplate is provided for ItemsSource Bindings Avoid 0xc000027b Application Crash when no DataTemplate is provided for ItemsSource Bindings in SettingsExpander Aug 29, 2023
@niels9001
Copy link
Collaborator

@RobertK66 That's great feedback.. would you mind creating a new issue for your latest comment so we can pick up the discussion there?

@RobertK66
Copy link
Author

Here you are #199

@RobertK66
Copy link
Author

Ok, I got the point of closing #199.

But the really dis-encouraging thing here is: As a newbie playing around with XAML GUI I do get a 'satisfying result' (ok not nicely rendered but running!) during development and debug. But it is a fatal bug when delivered and installed! Thinking of using WinUi3 (as first serious successor to WPF) in a professional setting one is forced to introduce a really thorough test step on the installed product to find this sort of problems.

I saw the video provided with the documentation about the 'Stowed Exception C000027B'. As a senior developer with 30+ years I do understand the complexities of your 'runtime environment'.

That said, this now is not about this specific issue ( misuse of component -> better doku ) anymore.
But wouldn't there be a possibility to use some sort of initialization callback and check the availability of the DataTemplate in this 'specific customized component'? As I understood you comment above, you are aware of the fact that your code NEEDS a SettingsCard in the root of the template. It would be nice for a developer to be informed about that by any means (raised exception, or at least some warning output in the debug console).

I do appreciate your work and seeing Microsofts turnaround from closed to open source is really amazing. Getting a feedback channel from developer to developer is very encouraging and this is how it should be. Thx. a lot and greetings from Vienna, Austria 😄 !

@michael-hawker michael-hawker moved this from 🆕 New to 📋 Backlog in Toolkit 8.x Aug 30, 2023
@RobertK66
Copy link
Author

RobertK66 commented Sep 25, 2023

Having @michael-hawker s comment on #199 in my head

There's no controls that provide anything like this out-of-the-box (in OS or WinUI), and it's not something we've ever done before,

, while strolling around in several repositories, I found this 😄 :
microsoft/microsoft-ui-xaml#35

Yes this is an old commit, but I just have a gut feeling that this TextBlock could be the reason that I could run my original code in VS. Maybe having a DefaultTemplate available to avoid fatal situations is not that bad idea at all 😉 ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
Status: 📋 Backlog
Development

No branches or pull requests

3 participants