it-swarm.com.de

ComboBox SelectedItem mit MVVM binden

Ich habe ein Problem mit dem SelectedItem in meiner ComboBox

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

Here is anything okWenn ich die ComboBox öffne, sehe ich die Werte.

enter image description here Wenn ich einen Artikel auswähle, wird der ausgewählte Artikel nicht angezeigt.

Hat jemand eine Idee?

In meinem ViewModel habe ich folgende zwei Eigenschaften:

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

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

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

Dies sind einige Eigenschaften aus der Klasse:

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: Folgendes geschieht, wenn ich die Eigenschaft DisplayMemberPath entferne: enter image description here

28
René Winter

Sie scheinen die Eigenschaften Ihrer ComboBox unnötigerweise einzustellen. Sie können die DisplayMemberPath- und SelectedValuePath-Eigenschaften entfernen, die zu unterschiedlichen Zwecken verwendet werden. Es könnte für Sie eine Idee sein, sich den Unterschied zwischen SelectedItem, SelectedValue und SelectedValuePath post hier anzusehen, um eine Erklärung dieser Eigenschaften zu erhalten. Versuche dies:

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

Darüber hinaus ist die Verwendung Ihrer displayPeriod-Eigenschaft sinnlos, da das WPF Framework die ToString-Methode automatisch für Objekte aufrufen würde, die angezeigt werden müssen und für die nicht explizit eine DataTemplate eingerichtet ist.


UPDATE >>>

Da ich Ihren gesamten Code nicht sehen kann, kann ich Ihnen nicht sagen, was Sie falsch machen. Stattdessen kann ich Ihnen nur ein vollständiges Arbeitsbeispiel geben, wie Sie das erreichen, was Sie wollen. Ich habe die sinnlose displayPeriod-Eigenschaft und auch Ihre SalesPeriodVO-Eigenschaft aus Ihrer Klasse entfernt, da ich nichts davon weiß ... vielleicht ist das die Ursache Ihres Problems. Versuche dies:

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

Dann habe ich dem Ansichtsmodell zwei Eigenschaften hinzugefügt:

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

Dann initialisiert die Sammlung mit Ihren Werten:

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

Und dann gebunden only diese beiden Eigenschaften an eine ComboBox:

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

Das ist es ... das ist alles, was Sie für ein perfekt funktionierendes Beispiel brauchen. Sie sollten sehen, dass die Anzeige der Elemente von der ToString-Methode ohne Ihrer displayPeriod-Eigenschaft stammt. Hoffentlich können Sie Ihre Fehler aus diesem Codebeispiel herausfinden.

42
Sheridan

Ich hatte ein ähnliches Problem, bei dem die Bindung SelectedItem - nicht aktualisiert wurde, als ich etwas in der Combobox auswählte. Mein Problem war, dass ich pdateSourceTrigger = PropertyChanged für die Bindung setzen musste.

<ComboBox ItemsSource="{Binding SalesPeriods}" 
          SelectedItem="{Binding SelectedItem, UpdateSourceTrigger=PropertyChanged}" />
0
<!-- 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);
            }
        }
0
Zoyeb Shaikh