AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.96k stars 2.25k forks source link

ComboBox in collection control doesn't display initial value #17230

Open Earlh21 opened 1 month ago

Earlh21 commented 1 month ago

Describe the bug

When you have a collection control bound to an ObservableCollection of models, ComboBoxes inside the control don't display the initial value of the model properties they're bound to.

This occurs regardless of when or how items are added to the collection or what the type of the ComboBox values are.

To Reproduce

  1. Create a observable model class TestModel with a string property.
  2. Create a view model with an ObservableCollection[string] property of sample values, and an ObservableCollection[TestModel] property.
  3. In the view model's constructor, add a TestModel to the collection.
  4. In the view's XAML, create an ItemsControl bound to the ObservableCollection[TestModel].
  5. In the ItemsControl's data template, add a ComboBox with ItemsSource bound to the sample values, and SelectedItem bound to TestModel's string property.
  6. Run the app and observe the lack of initial value in the ComboBox.

Example repo showing the issue for two data types (string and enum), and a working ComboBox that isn't based on a collection: https://github.com/Earlh21/ComboBoxTest. There's also a button to add more TestModels dynamically - their ComboBoxes also lack initial values.

Expected behavior

I expected to see the TestModel's initial string property value in the ComboBox.

Avalonia version

11.1.0

OS

Windows

Additional context

No response

rabbitism commented 1 month ago

Your repo is private

Earlh21 commented 1 month ago

Your repo is private

It's public now.

timunie commented 1 month ago

@Earlh21 now I see. What happens here is, that the DataTemplate is not a child of MainWindow when it is build and thus it has no Items. No Items --> Selected item is being reset. To overcome this, I suggest to give your Window a name (Root for example) and bind to it via named element syntax:

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:ComboBoxTest.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="ComboBoxTest.Views.MainWindow"
        x:DataType="vm:MainWindowViewModel"
        Icon="/Assets/avalonia-logo.ico"
+       x:Name="Root"
        Title="ComboBoxTest">

    <Design.DataContext>
        <!-- This only sets the DataContext for the previewer in an IDE,
             to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
        <vm:MainWindowViewModel/>
    </Design.DataContext>

    <StackPanel Orientation="Vertical">
        <ComboBox ItemsSource="{Binding EnumValues}" SelectedItem="{Binding ModelEnumProperty.EnumProperty}"/>

        <ItemsControl ItemsSource="{Binding EnumModels}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
!                   <ComboBox ItemsSource="{Binding #Root.((vm:MainWindowViewModel)DataContext).EnumValues}"
                              SelectedItem="{Binding EnumProperty}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

+[...]

From what I can tell, this is by design. However will ask the team before closing this issue.

Earlh21 commented 1 month ago

Right, I didn't even think about the relative reference being the issue. Yes that works, thank you.

xlxdd commented 1 week ago

Though I don't fully understand,the solution works.