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.