【问题标题】:Binding ComboBox SelectedItem using MVVM使用 MVVM 绑定 ComboBox SelectedItem
【发布时间】:2013-11-07 01:49:45
【问题描述】:

我的 ComboBox 中的 SelectedItem 有问题。

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

如果我打开 ComboBox,我会看到值。

如果我选择一个项目,所选项目将不会显示。

有人有想法吗?

在我的 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");
        }
    }
}

这些是该类的一些属性:

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);
}

编辑: 如果我删除属性 DisplayMemberPath,会发生以下情况:

【问题讨论】:

  • 您应该创建一个沙盒应用程序。只留下一个组合框,你的 viemodels 删除其他所有内容。然后你应该尝试重现这个问题。你可能无法做到。然后比较这两个应用程序,看看哪个差异会导致这种行为。我怀疑问题出在您提供的代码中。另请注意,您的组合框有一个名称。查看代码隐藏文件,看看是否有一些代码与选择有关。

标签: c# wpf data-binding mvvm binding


【解决方案1】:

您似乎在您的ComboBox 上设置了不必要的属性。您可以删除具有不同用途的DisplayMemberPathSelectedValuePath 属性。您可以在此处查看Difference between SelectedItem, SelectedValue and SelectedValuePath 帖子以了解这些属性的说明。试试这个:

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

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


更新>>>

由于我看不到您的所有代码,因此我无法告诉您您做错了什么。相反,我所能做的就是为您提供一个完整的工作示例,说明如何实现您想要的。我已经从您的班级中删除了毫无意义的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"));
        }
    }
}

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

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"); }
}

然后用你的值初始化集合:

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

然后数据将这两个属性绑定到ComboBox

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

就是这样......这就是完美工作示例所需要的一切。您应该看到项目的显示来自ToString 方法没有您的displayPeriod 属性。希望您可以通过此代码示例解决您的错误。

【讨论】:

  • 这并没有回答这个问题。设置这些属性不应导致在给定上下文中描述的行为。
  • 我试图删除这些属性,但它不起作用。我已经编辑了第一个帖子。
  • @NikitaBrizhak 我接受我的原始答案没有为用户提供完整的解决方案。然而,在回答了很多这样的问题后,我意识到,由于多种原因,例如缺乏信息或问题作者的理解,很少能立即提供答案。因此,我已经养成了分阶段回答这些问题的习惯,您刚刚看到了第一个问题。现在您可以看到第二阶段。也许将来您可以让知名用户获得怀疑的好处,并将这些类型的 cmets 留给新用户?
  • @Sheridan,我只是指出,虽然您的建议从代码审查员的角度来看是有效的,但他们并没有试图解决手头的问题。这没有什么坏处,不是吗?对不起,如果我的评论听起来冒犯,我不是那个意思。
  • @Sheridan,“也许将来您可以让知名用户免于怀疑,并将这些类型的 cmets 留给新用户?” -> 很有趣:-)
【解决方案2】:

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

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

【讨论】:

  • 这个是为我做的,荣誉
【解决方案3】:
<!-- 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);
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-10
    • 2012-06-19
    • 2011-11-01
    • 2016-09-25
    • 2017-02-20
    • 2015-06-28
    • 2017-04-30
    • 2023-04-03
    相关资源
    最近更新 更多