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?
source to share
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}">
source to share