简体   繁体   中英

C# - WPF ComboBox not setting default value in Code-behind

Following code of my WPF app is showing the default value as blank instead of CA . I've tested in debug mode that the cmbStates.SelectedValue is showing NULL after I move to the next line while using F11 in VS2017 . I've tried moving the code to Windows loaded event but still the exact same behavior.

Note :

  1. According to this post it should work, but it's not. Maybe, my case is a bit different
  2. The code successfully displays the comboBox values but the top of the comboBox is blank unless I manually select a particular value for the comboBox.

Question : What I may be missing here and how can we make it work?

XAML :

<Window x:Class="WpfTestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
....
....
>
 <Grid>
....
....
<ComboBox x:Name="cmbStates" IsEditable="True" SelectedValuePath="Content" SelectionChanged="cmbStates_SelectionChanged" />
....
....

  </Grid>
</Window>

Code Behind for MainWindow :

....
public MainWindow()
{
    InitializeComponent();

    cmbStates.ItemsSource = new List<string>() {"OH", "VA", "CA", "TN", "CA", "DE"};
    cmbStates.SelectedValue =  "CA";
}
....

UPDATE :

Please note that the question is more specific to setting the default value in Code Behind and not in XAML because the list is quite longer than shown in this post (for brevity), and that the default value is not always "CA" - it varies based on the business requirements. You can think of "CA" as some string variable value instead, but the idea is the same.

The issue why the selected item is not displayed is this xml attribute:

SelectedValuePath="Content"

While the SelectedValue is set to "CA", it is not displayed, because you advised your view to check for the property Content for the SelectedItem , which of course is not present for the string that you use.

In order to make it work for your above example, you would simply remove that attribute within your combobox.

On the other hand, if your bound items are classes and you would need one field to display and another one as the value / identifier, the SelectedValuePath would make sense, in combination with the DisplayMemberPath attribute.

Let's say your items would look something like this:

public class SomeModel
{
    public string Abbreviation { get; set; }
    public string Content { get; set; }

    public SomeModel(string abbreviation, string content)
    {
        Abbreviation = abbreviation;
        Content = content;
    }
}

In this case the ComboBox would look like this:

<ComboBox x:Name="cmbStates" IsEditable="True" SelectedValuePath="Abbreviation" DisplayMemberPath="Content" SelectionChanged="cmbStates_SelectionChanged" />

This way the Abbreviation property is the actuall value of the ComboBoxItem and the Content is used as the display for the ComboBox . Now your MainWindow constructor would look like this:

public MainWindow()
{
    InitializeComponent();

    cmbStates.ItemsSource = new List<SomeModel>
    {
        new SomeModel("OH","Ohio"), new SomeModel("VA","Virginia"), new SomeModel("CA","California "),
        new SomeModel("TN","Tennessee"), new SomeModel("DE","Delaware")
    };
    cmbStates.SelectedValue = "CA";
}

Besides this case, I would advise yout to look into WPF data binding and WPF MVVM pattern .

Since you set the ItemsSource of your ComboBox to a List<string> , you should set the SelectedItem property to a string that is included in this list and remove SelectedValuePath="Content" from your XAML as a string has no Content property:

cmbStates.ItemsSource = new List<string>() {"OH", "VA", "CA", "TN", "CA", "DE"};
cmbStates.SelectedItem =  "CA";

XAML:

<ComboBox x:Name="cmbStates" IsEditable="True" SelectionChanged="cmbStates_SelectionChanged" />

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