简体   繁体   中英

how to set combobox default value in wpf using binding in mvvm when manually setting combobox items

I am using mvvm in wpf. I am setting a form to update user data. I have a combobox to select gender of user. i have added combobox items manually in source. when loading data to form all fields other fields are displaying correctly. but combobox is not displaying anything. I have used twoWay binding and the values i am selecting from form are getting in the viewModel.I have been searching for hours and found many similar problem, but nothing worked for me. I am inserting my code segment bellow. Please give me a solution.

<ComboBox 
    Grid.Column="2" 
    SelectedItem="{Binding SelectedEmployees.gender, Mode=TwoWay}" 
    SelectedValue="{Binding SelectedEmployees.gender, Mode=TwoWay}"
    >
    <ComboBoxItem Content="Male"/>
    <ComboBoxItem Content="Female"/>
</ComboBox> 

my viewModel code is as bellow

class EmployeesModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private iServiceClient serviceClient = new iServiceClient();
    public EmployeesModel()
    {
        this.RefreshEmployees();
    }

    private void RefreshEmployees()
    {
        this.serviceClient.GetAllEmployeesCompleted += (s, e) =>
          {
              this.employees = e.Result;
          };

        this.serviceClient.GetAllEmployeesAsync();
    }

    private IEnumerable<Employee> employees;
    public IEnumerable<Employee> Employees
    {
        get
        {
            return this.employees;
        }
        set
        {
            this.employees = value;
            this.OnPropertyChanged("Employees");
        }
    }

    private Employee selectedEmployees;
    public Employee SelectedEmployees
    {
        get
        {
            return this.selectedEmployees;
        }
        set
        {
            this.selectedEmployees = value;
            this.OnPropertyChanged("SelectedEmployees");
        }
    }

    public void OnPropertyChanged(string PropertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }

}

and SelectedEmployees class is

public class Employee
{
    [Key]
    public int id { get; set; }
    public DateTime JoiningDate { get; set; }
    public string name { get; set; }
    public string gender { get; set; }
    public string mobile { get; set; }
    public string post { get; set; }
    public string salaryType { get; set; }
    public decimal salary { get; set; }
    public string docname { get; set; }
    public int validit { get; set; }
}

I suspect that SelectedEmployees.gender is not type comboboxitem.
Taking the shortcut of creating comboboxitems directly in the combobox is a bad move.

When I do:

    xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Window.DataContext>
    <local:MainWIndowViewModel/>
</Window.DataContext>
<Window.Resources>
    <x:Array Type="sys:String" x:Key="Genders">
        <sys:String>Male</sys:String>
        <sys:String>Female</sys:String>
    </x:Array>
</Window.Resources>
<Grid>
    <ComboBox 
     SelectedItem="{Binding gender, Mode=TwoWay}" 
        ItemsSource="{StaticResource Genders}"
        />
</Grid>

I get a string instead of a comboboxitem in my bound gender. You probably want something rather more like that.

This is probably the best approach, particularly if you mean to learn MVVM: Use an enum type for Gender. "LOL" is never a valid gender so don't let anybody try to use it. Populate the ComboBox by binding it to a static collection. Initialize SelectedEmployees.gender to the value you want to be the default and the binding will take care of the rest.

<ComboBox 
    SelectedItem="{Binding SelectedEmployees.gender}" 
    ItemsSource="{Binding SelectedEmployees.Genders}"
    /> 

C#

public class SelectedEmployeesViewModel : ViewModelBase
{
    /* ...other stuff... */

    private Gender _gender = Gender.Male;
    public Gender gender
    {
        get { return _gender; }
        set
        {
            if (value != _gender)
            {
                _gender = value;
                OnPropertyChanged();
            }
        }
    }
}

public enum Gender
{
    Male, Female
}

public static class EnumValues
{
    public static IEnumerable<Gender> Genders => Enum.GetValues(typeof(Gender)).Cast<Gender>();
}

There are other approaches. I advise against going with a string, but this is illustrative at least:

    private String _gender = "Male";
    public String gender
    {
        get { return _gender; }
        set
        {
            if (value != _gender)
            {
                _gender = value;
                OnPropertyChanged();
            }
        }
    }

Does your SelectedEmployees class implement INotifyPropertyChanged , and does SelectedEmployees.gender raise PropertyChanged when its value changes?

Get rid of Mode=TwoWay on the binding; you don't need to do that explicitly. It's the default for any binding you put on ComboBox.SelectedValue or on ComboBox.SelectedItem .

As Andy pointed out in comments, your SelectedValue and SelectedItem are both going to be instances of ComboBoxItem , because that's how you populated your ComboBox. The string you want is in the Content property of the ComboBoxItems, so use SelectedValuePath to tell the ComboBox about that, and bind to the SelectedValue property. SelectedItem will be the ComboBoxItem itself, which is useless to you.

<ComboBox 
    SelectedValue="{Binding SelectedEmployees.gender}" 
    SelectedValuePath="Content"
    >
    <ComboBoxItem Content="Male" />
    <ComboBoxItem Content="Female" />
</ComboBox>

Here's another approach: Populate the ComboBox with strings.

<ComboBox 
    SelectedItem="{Binding SelectedEmployees.gender}" 
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    >
    <sys:String>Male</sys:String>
    <sys:String>Female</sys:String>
</ComboBox> 

See Andy's answer for yet another way to populate the ComboBox with strings via ItemsSource .

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