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:
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?
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}">
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With