Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why I get exception when setting ComboBox.SelectedIndex?

I am trying to learn about bindings and XAML. I have a very simple example, where I bind an array of strings to a combobox defined in XAML. I also want to set the selected index.

I am getting an exception:

Value does not fall within the expected range.

with the SelectedIndex property.

Here my XAML for a UWP application.

<StackPanel Background="{ThemeResource applicationPageBackgroundThemeBrush}">
    <ComboBox Name="BrowserCombo" ItemsSource="{x:Bind ComboStrings}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding}"/>
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
</StackPanel>

and the code behind

public sealed partial class MainPage : Page
{
    private string[] comboStrings = { "One", "Two", "Three" };
    public List<String> ComboStrings
    {
       get { return new List<string>(comboStrings); }
    }

    public MainPage()
    {
        this.InitializeComponent();
        DataContext = this;
        BrowserCombo.SelectedIndex = 1;
    }

    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        // BrowserCombo.SelectedIndex = 1;
    }
}

I want to have it very simple, so no MVVM - I still need to learn this concept.

Remarks:

  1. I can put SelectedIndex in the XAML file. Same problem.
  2. If I put the SelectedIndex in the Page_Loaded event handler, it works fine.
  3. In a classic desktop XAML (aka WPF) there will be no problem.

It seems to be that the item list will be populated differently between XAML-WinRt and XAML-WPF. What is the earliest point to access the SelectedIndex property?

like image 815
Money Avatar asked Oct 28 '25 10:10

Money


1 Answers

You get this exception because your ItemsSource is still null when you try to set BrowserCombo.SelectedIndex = 1; in the page's constructor. You are using x:Bind - if you debug the generated MainPage.g.cs file and put some breakpoints there:

public void Loading(global::Windows.UI.Xaml.FrameworkElement src, object data)
{
    this.Initialize();
}

public void Initialize()
{
    if (!this.initialized)
    {
        this.Update();
    }
}

public void Update()
{
    this.Update_(this.dataRoot, NOT_PHASED);
    this.initialized = true;
}

You will see that x:Bind is being resolved in Loading event - this explains why in constructor you still have null in ItemsSource.

The other thing is that with old Binding - it is resolved when you set DataContext = this;, but you are using x:Bind and in fact you don't need to set the DataContext - it doesn't change anything here. If you replace ItemsSource="{x:Bind ComboStrings}" with ItemsSource="{Binding ComboStrings}" then your code should work, otherwise you may remove the line DataContext = this;.

Another interesting thing is that the order of defined bindings in XAML, can also cause similar troubles - for example if you define your ComboBox like this:

<ComboBox Name="BrowserCombo" SelectedIndex="{x:Bind Index}" ItemsSource="{x:Bind ComboStrings}">

then you will also get exception - SelectedIndex is being resolved before the collection is set up. Opposite to the situation when it works fine:

<ComboBox Name="BrowserCombo" ItemsSource="{x:Bind ComboStrings}" SelectedIndex="{x:Bind Index}">
like image 128
Romasz Avatar answered Oct 30 '25 04:10

Romasz