简体   繁体   English

手动设置组合框项目时,如何使用mvvm中的绑定在wpf中设置组合框默认值

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

I am using mvvm in wpf. 我在WPF中使用mvvm。 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. 我使用了twoWay绑定,并且我从表单中选择的值都进入了viewModel。我一直在搜索数小时,发现了许多类似的问题,但对我没有任何帮助。 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 我的viewModel代码如下

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 并且SelectedEmployees类是

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. 我怀疑SelectedEmployees.gender不是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. 在绑定的性别中,我得到的是字符串而不是comboboxitem。 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. 这可能是最好的方法,特别是如果您要学习MVVM:对Gender使用枚举类型。 "LOL" is never a valid gender so don't let anybody try to use it. “ LOL”从来都不是有效的性别,因此不要让任何人尝试使用它。 Populate the ComboBox by binding it to a static collection. 通过将ComboBox绑定到静态集合来填充它。 Initialize SelectedEmployees.gender to the value you want to be the default and the binding will take care of the rest. SelectedEmployees.gender初始化为您想要作为默认值的值,绑定将完成其余工作。

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

C# 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? 您的SelectedEmployees类是否实现INotifyPropertyChanged ,并且SelectedEmployees.gender的值更改时是否引发PropertyChanged

Get rid of Mode=TwoWay on the binding; 摆脱绑定上的Mode=TwoWay you don't need to do that explicitly. 您无需明确地执行此操作。 It's the default for any binding you put on ComboBox.SelectedValue or on ComboBox.SelectedItem . 这是放置在ComboBox.SelectedValueComboBox.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. 正如Andy在评论中指出的那样,您的SelectedValue和SelectedItem都将是ComboBoxItem实例,因为这就是填充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. 所需的字符串在ComboBoxItems的Content属性中,因此请使用SelectedValuePath告诉ComboBox有关此内容,并绑定到SelectedValue属性。 SelectedItem will be the ComboBoxItem itself, which is useless to you. SelectedItem将是ComboBoxItem本身,对您没有用。

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

Here's another approach: Populate the ComboBox with strings. 这是另一种方法:用字符串填充ComboBox。

<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 . 有关通过ItemsSource用字符串填充ComboBox的另一种方法,请参见Andy的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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