web-dev-qa-db-fra.com

Liaison ComboBox SelectedItem à l'aide de MVVM

J'ai un problème avec le SelectedItem dans mon ComboBox

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

Here is anything ok Si j'ouvre la ComboBox, je vois les valeurs.

enter image description hereSi je sélectionne un élément, celui-ci ne sera pas affiché.

Quelqu'un a une idée?

Dans mon ViewModel, j'ai ces deux propriétés:

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

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

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

Voici quelques propriétés de la classe:

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: Ce qui suit se produit si je supprime la propriété DisplayMemberPath: enter image description here

28
René Winter

Vous semblez définir inutilement des propriétés sur votre ComboBox. Vous pouvez supprimer les propriétés DisplayMemberPath et SelectedValuePath qui ont des utilisations différentes. Ce serait peut-être une idée pour vous de jeter un œil à l'article Différence entre SelectedItem, SelectedValue et SelectedValuePath ici pour une explication de ces propriétés. Essaye ça:

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

De plus, il est inutile d'utiliser votre propriété displayPeriod, car WPF Framework appellerait automatiquement la méthode ToString pour les objets qu'il a besoin d'afficher et pour lesquels explicitement aucune DataTemplate n'est configurée.


MISE À JOUR >>>

Comme je ne vois pas tout votre code, je ne peux pas vous dire ce que vous faites de travers. Au lieu de cela, tout ce que je peux faire est de vous fournir un exemple de travail complet sur la manière d'atteindre ce que vous voulez. J'ai supprimé la propriété displayPeriod inutile ainsi que votre propriété SalesPeriodVO de votre classe, car je n'en sais rien ... c'est peut-être la cause de votre problème ??. Essaye ça:

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

Ensuite, j'ai ajouté deux propriétés dans le modèle de vue:

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

Puis initialisé la collection avec vos valeurs:

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

Et ensuite, les données liées seulement ces deux propriétés à une ComboBox:

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

C'est ça ... c'est tout ce dont vous avez besoin pour un exemple qui fonctionne parfaitement. Vous devriez voir que l'affichage des éléments provient de la méthode ToString, sans votre propriété displayPeriod. Espérons que vous pourrez résoudre vos erreurs à partir de cet exemple de code.

42
Sheridan
<!-- 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