简体   繁体   中英

Combobox not binding initial value when page first shown

The Scenario

I have a UserControl which contains a couple of controls, one of which is a ComboBox . The UserControl is conatined with a Page .

The UserControl exposes a couple of dependency properties to allow the Items and SelectedValue of the ComboBox to be accessed. These are defined as follows:

public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(int?), typeof(CustomComboBox), new FrameworkPropertyMetadata((int?)null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public int? SelectedValue
{
    get { return (int?)this.GetValue(SelectedValueProperty); }
    set { this.SetValue(SelectedValueProperty, value); }
}

public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(List<ComboItem>), typeof(CustomComboBox), new FrameworkPropertyMetadata((List<ComboItem>)new List<ComboItem>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public List<ComboItem> Items
{
    get { return (List<ComboItem>)this.GetValue(ItemsProperty); }
    set { this.SetValue(ItemsProperty, value); }
}

These are binded to the ComboBox control as follows:

<ComboBox ItemsSource="{Binding Path=Items, ElementName=ThisControl}" DisplayMemberPath="Text" SelectedValuePath="ID" SelectedValue="{Binding Path=SelectedValue, ElementName=ThisControl, UpdateSourceTrigger=PropertyChanged}" />

Where the UserControl is named "ThisControl" .

Also, in the above, ComboItem is a class which contains the definitions for each item, namely two properties called ID and Text . The idea here is that ID is the key that is stored in the database, and Text is the user friendly value that is displayed in the list.

When the Page containing the UserControl is created (using the Constructor), the ComboBox items list is populated with the following code:

MyComboBox.Items.Clear();
MyComboBox.Items.Add(new ComboItem() { ID = 1, Text = "One" });
MyComboBox.Items.Add(new ComboItem() { ID = 2, Text = "Two" });

Finally, the SelectedValue is binded to a class property via XML like so:

<c:CustomComboBox x:Name="MyComboBox" SelectedValue="{Binding Path=MyClassInstance.ItemID}" />

where the property ItemID is of type int . It is important to note that the class instance is set after the combo box items are populated.

The Problem

When the page is first shown, the initial selected value is not set correctly - it is an empty item selection. I can assure that the ItemID property is already set to a valid value (ie 1 ).

When an item is selected from the ComboBox , the binding does successfully set the ItemID property, and is correctly persisted to the database upon a 'save' function.

One strange behavior, which may help to identity the problem, is that if the window containing the Page is closed, and then re-opened. The ComboBox does get th correct initial value - and that is regardless of the ComboBox being set on first attempt, or otherwise.

So, the question is: Why is the initial value not shown the first time the page is displayed?

OK, I was doing some refactoring to improve how I populate the ComboBox Items and I seem to have stumbled across the solution...

The problem seems to be related to the following piece of code that populates the list items:

MyComboBox.Items.Clear();
MyComboBox.Items.Add(new ComboItem() { ID = 1, Text = "One" });
MyComboBox.Items.Add(new ComboItem() { ID = 2, Text = "Two" });

The solution is to directly set the Items property, rather than to clear it and populate it:

MyComboBox.Items = GetMyList();

Where GetMyList() is returning a List<ComboItem> type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM