Microsoft-ui-xaml: Question: ObservableCollection for WinUI Win32

Created on 20 May 2020  路  10Comments  路  Source: microsoft/microsoft-ui-xaml

Microsoft.UI.Xaml.Interop.INotifyCollectionChanged is missing from WinUI Win32 namespaces. Using the default ObservableCollection doesn't work with ItemsControls and implementing Windows.UI.Xaml.Interop.INotifyCollectionChanged throws _The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))_

So what is the correct way to notify ItemsControl for a CollectionChanged and also which INotifyPropertyChanged works with Binding?

bug winui3preview

Most helpful comment

@stevenbrix Sorry for the delay. Forgot about this issue due to Build.
Exception is thrown if you try to create custom observable collection and implement Windows.UI.Xaml.Interop.INotifyCollectionChanged interface.

When using ObservableCollection there is no exception but changes are not reflected on the UI.

All 10 comments

This is a duplicate of #1557 and originally #1981

This really should have been fixed before the preview though. ObservableCollection is fundamental to ALL user interfaces.

This is slightly different than the issues linked here. This is for a Win32 app which is going through CSWinrt which should have a solution for this issue. Looks like a CSWinrt bug. @stevenbrix for FYI

Can you share a repro app?

I'm not seeing a crash, but it doesn't seem to be working. I have a repro here that is using markup like this:

<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
     <Button Click="myButton_Click" x:Name="myButton">Click me</Button>
    <ItemsControl ItemsSource="{x:Bind MyItems}"/>
    <ItemsControl ItemsSource="{Binding MyItems}"/>
</StackPanel>
public MainWindow()
{
    MyItems.Add("hi");
    MyItems.Add("goodbye");

    this.InitializeComponent();
}

private void myButton_Click(object sender, RoutedEventArgs e)
{
    MyItems.Add("clicked");
}

ObservableCollection<string> MyItems { get; } = new ObservableCollection<string>();

WinUIDesktopCS0515-3.zip

Not sure if this is related to https://github.com/microsoft/CsWinRT/issues/272

@stevenbrix Sorry for the delay. Forgot about this issue due to Build.
Exception is thrown if you try to create custom observable collection and implement Windows.UI.Xaml.Interop.INotifyCollectionChanged interface.

When using ObservableCollection there is no exception but changes are not reflected on the UI.

I spent some time with this issue, too while I realized that there is a problem with INotifyCollectionChanged in WinUI Win32.
I think that this is a must to have basic functionality. Could this be please somehow (fixed) prioritized for the next preview, so we could explore/try out WinUI 3 preview with more complex scenarios and help you to find another possible issues? This is a blocker for ItemsControl based controls in MVVM apps.

As a workaround I tried to raise NotifyPropertyChanged of the whole collection during item Added or Removed, but it didn't help.

```C#
NotifyPropertyChanged(nameof(Items));
//where Items is ReadOnlyObservableCollection Items ...

```XAML
<ListBox ItemsSource="{x:Bind ViewModel.ProductsListViewModel.Items, Mode=OneWay}" />

Thank you

I don't know why it works, however I found a workaround:

// Add this class
public static class BindingUtils
{
    public static IEnumerable Fix(IEnumerable x) => x.OfType<object>();
}
<!-- Change binding expressions to use above class. Items is ObservableCollection<T>. -->
<!-- before -->
ItemsSource="{x:Bind ViewModel.Items}"

<!-- after -->
ItemsSource="{x:Bind local:BindingUtils.Fix(ViewModel.Items), Mode=OneWay}"

@runceel, thank you for the information! Do you have to specify OneWay for the binding to work?

@stevenbrix, Yes, I need OneWay to work the workaround.
Updating the binding might be triggered PropertyChanged event of ObservableCollection<T>.
I think the Fix method returns a different instance every call, and then ItemsControl refresh all items.

@runceel @stevenbrix I tried a similar workaround. I created a new (Immutable) ObservableCollection during on Added/Removed notifications, but this is not good for performance IMO.
Proper MVU could maybe help in this case.

This issue should be fixed in WinUI3 Preview2. Thanks!

Was this page helpful?
0 / 5 - 0 ratings