C# 使用 MVVM 绑定 ComboBox SelectedItem

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19632270/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 15:28:23  来源:igfitidea点击:

Binding ComboBox SelectedItem using MVVM

c#wpfdata-bindingmvvmbinding

提问by René Winter

I have a problem with the SelectedItemin my ComboBox.

我的ComboBox 中SelectedItem有问题。

<ComboBox Name="cbxSalesPeriods"
        ItemsSource="{Binding SalesPeriods}"
        DisplayMemberPath="displayPeriod"
        SelectedItem="{Binding SelectedSalesPeriod}"
        SelectedValuePath="displayPeriod"
        IsSynchronizedWithCurrentItem="True"/>

Here is anything okIf I open the ComboBox, I see the values.

这里没什么问题如果我打开 ComboBox,我会看到这些值。

enter image description hereIf I select an item, the selected Item won't be shown.

在此处输入图片说明如果我选择一个项目,则不会显示所选项目。

Has anybody an idea?

有人有想法吗?

In my ViewModel I have these two properties:

在我的 ViewModel 我有这两个属性:

public ObservableCollection<SalesPeriodVM> SalesPeriods { get; private set; }

private SalesPeriodVM selectedSalesPeriod;
public SalesPeriodVM SelectedSalesPeriod
{
    get { return selectedSalesPeriod; }

    set 
    {
        if (selectedSalesPeriod != value)
        {
            selectedSalesPeriod = value;
            RaisePropertyChanged("SelectedSalesPeriod");
        }
    }
}

These are a few properties from the class :

这些是类中的一些属性:

public SalesPeriodVO Vo
{
    get { return period; }
}

public int Year
{
    get { return period.Year; }
    set
    {
        if (period.Year != value)
        {
            period.Year = value;
            RaisePropertyChanged("Year");
        }
    }
}

public int Month
{
    get { return period.Month; }
    set
    {
        if (period.Month != value)
        {
            period.Month = value;
            RaisePropertyChanged("Month");
        }
    }
}

public string displayPeriod { 
    get
    {
        return this.ToString();
    }
}

public override string ToString()
{
    return String.Format("{0:D2}.{1}", Month, Year);
}


EDIT: The Following happens If I remove the Property DisplayMemberPath: enter image description here

编辑:如果我删除属性 DisplayMemberPath,则会发生以下情况: 在此处输入图片说明

采纳答案by Sheridan

You seem to be unnecessarily setting properties on your ComboBox. You can remove the DisplayMemberPathand SelectedValuePathproperties which have different uses. It might be an idea for you to take a look at the Difference between SelectedItem, SelectedValue and SelectedValuePathpost here for an explanation of these properties. Try this:

您似乎不必要地在ComboBox. 您可以删除具有不同用途的DisplayMemberPathSelectedValuePath属性。您可以在这里查看SelectedItem、SelectedValue 和 SelectedValuePath 之间差异,以了解这些属性的说明。尝试这个:

<ComboBox Name="cbxSalesPeriods"
    ItemsSource="{Binding SalesPeriods}"
    SelectedItem="{Binding SelectedSalesPeriod}"
    IsSynchronizedWithCurrentItem="True"/>

Furthermore, it is pointless using your displayPeriodproperty, as the WPF Framework would call the ToStringmethod automatically for objects that it needs to display that don't have a DataTemplateset up for them explicitly.

此外,使用您的displayPeriod属性毫无意义,因为 WPF 框架会ToString自动为需要显示但没有DataTemplate明确设置的对象调用该方法。



UPDATE >>>

更新 >>>

As I can't see all of your code, I cannot tell you what you are doing wrong. Instead, all I can do is to provide you with a complete working example of how to achieve what you want. I've removed the pointless displayPeriodproperty and also your SalesPeriodVOproperty from your class as I know nothing about it... maybe that is the cause of your problem??. Try this:

由于我看不到您的所有代码,因此我无法告诉您您做错了什么。相反,我所能做的就是为您提供一个完整的工作示例,说明如何实现您想要的。我已经从你的班级中删除了毫无意义的displayPeriod财产和你的SalesPeriodVO财产,因为我对此一无所知......也许这就是你的问题的原因??。尝试这个:

public class SalesPeriodV
{
    private int month, year;

    public int Year
    {
        get { return year; }
        set
        {
            if (year != value)
            {
                year = value;
                NotifyPropertyChanged("Year");
            }
        }
    }

    public int Month
    {
        get { return month; }
        set
        {
            if (month != value)
            {
                month = value;
                NotifyPropertyChanged("Month");
            }
        }
    }

    public override string ToString()
    {
        return String.Format("{0:D2}.{1}", Month, Year);
    }

    public virtual event PropertyChangedEventHandler PropertyChanged;
    protected virtual void NotifyPropertyChanged(params string[] propertyNames)
    {
        if (PropertyChanged != null)
        {
            foreach (string propertyName in propertyNames) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            PropertyChanged(this, new PropertyChangedEventArgs("HasError"));
        }
    }
}

Then I added two properties into the view model:

然后我在视图模型中添加了两个属性:

private ObservableCollection<SalesPeriodV> salesPeriods = new ObservableCollection<SalesPeriodV>();
public ObservableCollection<SalesPeriodV> SalesPeriods
{
    get { return salesPeriods; }
    set { salesPeriods = value; NotifyPropertyChanged("SalesPeriods"); }
}
private SalesPeriodV selectedItem = new SalesPeriodV();
public SalesPeriodV SelectedItem
{
    get { return selectedItem; }
    set { selectedItem = value; NotifyPropertyChanged("SelectedItem"); }
}

Then initialised the collection with yourvalues:

然后使用您的值初始化集合:

SalesPeriods.Add(new SalesPeriodV() { Month = 3, Year = 2013 } );
SalesPeriods.Add(new SalesPeriodV() { Month = 4, Year = 2013 } );

And then data bound onlythese two properties to a ComboBox:

然后 data将这两个属性绑定到 a ComboBox

<ComboBox ItemsSource="{Binding SalesPeriods}" SelectedItem="{Binding SelectedItem}" />

That's it... that's all you need for a perfectly working example. You should see that the display of the items comes from the ToStringmethod withoutyour displayPeriodproperty. Hopefully, you can work out your mistakes from this code example.

就是这样......这就是一个完美工作示例所需的全部内容。您应该看到项目的显示来自没有您的属性的ToString方法。希望您可以从这个代码示例中解决您的错误。displayPeriod

回答by Zoyeb Shaikh

<!-- xaml code-->
    <Grid>
        <ComboBox Name="cmbData"    SelectedItem="{Binding SelectedstudentInfo, Mode=OneWayToSource}" HorizontalAlignment="Left" Margin="225,150,0,0" VerticalAlignment="Top" Width="120" DisplayMemberPath="name" SelectedValuePath="id" SelectedIndex="0" />
        <Button VerticalAlignment="Center" Margin="0,0,150,0" Height="40" Width="70" Click="Button_Click">OK</Button>
    </Grid>



        //student Class
        public class Student
        {
            public  int Id { set; get; }
            public string name { set; get; }
        }

        //set 2 properties in MainWindow.xaml.cs Class
        public ObservableCollection<Student> studentInfo { set; get; }
        public Student SelectedstudentInfo { set; get; }

        //MainWindow.xaml.cs Constructor
        public MainWindow()
        {
            InitializeComponent();
            bindCombo();
            this.DataContext = this;
            cmbData.ItemsSource = studentInfo;

        }

        //method to bind cobobox or you can fetch data from database in MainWindow.xaml.cs
        public void bindCombo()
        {
            ObservableCollection<Student> studentList = new ObservableCollection<Student>();
            studentList.Add(new Student { Id=0 ,name="==Select=="});
            studentList.Add(new Student { Id = 1, name = "zoyeb" });
            studentList.Add(new Student { Id = 2, name = "siddiq" });
            studentList.Add(new Student { Id = 3, name = "James" });

              studentInfo=studentList;

        }

        //button click to get selected student MainWindow.xaml.cs
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Student student = SelectedstudentInfo;
            if(student.Id ==0)
            {
                MessageBox.Show("select name from dropdown");
            }
            else
            {
                MessageBox.Show("Name :"+student.name + "Id :"+student.Id);
            }
        }

回答by Sakarias Stenb?ck

I had a similar problem where the SelectedItem-binding did not update when I selected something in the combobox. My problem was that I had to set UpdateSourceTrigger=PropertyChangedfor the binding.

我有一个类似的问题,即当我在组合框中选择某些内容时SelectedItem绑定没有更新。我的问题是我必须为绑定设置UpdateSourceTrigger=PropertyChanged

<ComboBox ItemsSource="{Binding SalesPeriods}" 
          SelectedItem="{Binding SelectedItem, UpdateSourceTrigger=PropertyChanged}" />