Why am I getting an exception when setting up 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 list defined in XAML. I also want to set the selected index.

I am getting an exception:

The value does not fall within the expected range.

with the SelectedIndex property.

Here's my XAML for a UWP app.

<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

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 this to be very simple, so there is no MVVM - I still need to learn this concept.

Notes:

  • I can put the SelectedIndex in a XAML file. Same problem.
  • If I put the SelectedIndex in the Page_Loaded event handler it works fine.
  • Classic desktop XAML (aka WPF) won't be a problem.

It seems that the list of items will populate differently between XAML-WinRt and XAML-WPF. What is the earliest access point for the SelectedIndex property?

+3


source to share


1 answer


You are getting this exception because your ItemsSource is still null when you try to set BrowserCombo.SelectedIndex = 1;

in the page constructor. You use x:Bind

- if you debug the generated MainPage.g.cs file and put some breakpoints in 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 what x:Bind

resolves when the event is loaded - this explains why in the constructor you still have null in the ItemsSource.

Another thing is that with the old Binding - it is allowed when you install DataContext = this;

but use x:Bind

, and you don't actually need to set the DataContext - it doesn't change anything. If you replace ItemsSource="{x:Bind ComboStrings}"

with ItemsSource="{Binding ComboStrings}"

then your code should work, otherwise you can remove the line DataContext = this;

.



Another interesting thing: the order of certain bindings in XAML can also cause similar problems - 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 an exception - SelectedIndex will be resolved before the collection is created. Opposite the situation where it works fine:

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

      

+2


source







All Articles