1 votes

Pourquoi le databinding échoue dans ListView (WPF) ?

J'ai un ListView dont l'ItemSource est réglé sur ma collection personnalisée.

J'ai défini un GridView CellTemplate qui contient une boîte combo comme ci-dessous :

           <ListView
            MaxWidth="850"                
            Grid.Row="1"
            SelectedItem="{Binding Path = SelectedCondition}"
            ItemsSource="{Binding Path = Conditions}"                 
            FontWeight="Normal"
            FontSize="11"                                
            Name="listview">
            <ListView.View>
                <GridView>
                    <GridViewColumn                           
                        Width="175"
                        Header="Type">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox                                       
                                    Style="{x:Null}"
                                    x:Name="TypeCmbox"
                                    Height="Auto"
                                    Width="150"
                                    SelectedValuePath="Key"
                                    DisplayMemberPath="Value"    
                                    SelectedItem="{Binding Path = MyType}"
                                    ItemsSource="{Binding Path = MyTypes}"
                                    HorizontalAlignment="Center" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
              </ListView>

public MyType : INotifyPropertyChanged

{ string Key ; string Value ;

public string Key { get { return _key; }
    set { _key = value; this.OnPropertyChanged("Key"); } }

public string Value { get { return _value; } 
    set { _value = value; this.OnPropertyChanged("Value"); } }

    public MyType ()
    {

    }

    public MyType (string key, string value)
    {
        _key = key;
        _value = value;
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion

}

 public void MoveUpExecuted()
    {
        int oldIndex = this.Conditions.IndexOf(_selectedCondition);

       //Check if the selected item is not the first item
        if (oldIndex != 0)
        {
            int newIndex = oldIndex - 1;
            this.Conditions.Move(oldIndex, newIndex);

        }           
    }

Ma collection personnalisée est l'ObservableCollection.

J'ai deux boutons - Move Up et Move Down - en haut du contrôle listview. Lorsque l'utilisateur clique sur le bouton "Move Up" ou "Move Down", j'appelle la méthode "Move" de la collection Observable.

Mais lorsque je déplace les lignes vers le haut et vers le bas, l'index sélectionné d'une boîte combo est -1.

Je me suis assuré que selectedItem n'est pas égal à null lors de l'exécution des commandes Move Up et Move Down.

S'il vous plaît, aidez-nous !

1voto

Tendlon Points 1072

Je ne comprends pas cette partie :

J'appelle les méthodes MoveUp et MoveDown de Collection Observable.

ObservableCollection ne possède pas de telles méthodes, du moins pas à ma connaissance ? Elle n'a pas non plus de notion d'élément courant ou similaire.

Je m'excuse si j'ai manqué quelque chose qui pourrait rendre ce message ignorant.

Au lieu de lier votre ListView à une ObservableCollection, vous pourriez la lier à une ICollectionView (dérivée de votre ObservableCollection). Si vous définissez IsSynchronizedWithCurrentItem=True sur ListView, vous n'aurez pas besoin de lier SelectedItem, il sera automatiquement lié à CurrentItem sur ICollectionView.

ICollectionView met également en œuvre les fonctions MoveCurrentToNext et MoveCurrentCurrentToPrevious qui peuvent être liées à partir de vos boutons (via ICommand).

EDITAR: Maintenant que de nouvelles informations sont sur la table, ma réponse ci-dessus n'est plus vraiment pertinente. Mais je ne connais pas (encore) la convention SO sur la manière de gérer cela, si je dois supprimer le message entièrement, éditer la réponse ci-dessus ou simplement ajouter la "nouvelle" réponse. Pour l'instant, je vais éditer ce message.

J'ai essayé de recréer votre projet et votre problème. J'espère avoir bien compris votre problème, et l'avoir recréé de manière similaire au moins.

Pour ce qui est du problème de la combobox qui ne conserve pas sa valeur lorsqu'elle est déplacée dans la liste, cela fonctionne pour moi.

Vous trouverez ci-dessous le code correspondant (dont une partie est cachée pour éviter trop de bruit).

Cela vous aide-t-il ?

public class MainWindowViewModel:INotifyPropertyChanged
    {
        private Condition _selectedCondition;
        public ObservableCollection<Condition> Conditions { get; set; }

        public Condition SelectedCondition
        {
            get
            {
                return _selectedCondition;
            }
            set
            {
                if (_selectedCondition != value)
                {
                    _selectedCondition = value;
                    OnPropertyChanged("SelectedCondition");
                }
            }
        }
...
public void MoveUpExecuted()
    {
        int oldIndex = this.Conditions.IndexOf(_selectedCondition);

        //Check if the selected item is not the first item
        if (oldIndex != 0)
        {
            int newIndex = oldIndex - 1;
            this.Conditions.Move(oldIndex, newIndex);
        }
    }

Et la classe de condition :

public class Condition : INotifyPropertyChanged
    {
        private MyType myType;
        public ObservableCollection<MyType> MyTypes { get; set; }

        public MyType MyType
        {
            get { return myType; }
            set
            {
                if (myType != value)
                {
                    myType = value;
                    OnPropertyChanged("MyType");

                }
            }
        }

        public Condition()
        {
            MyTypes = new ObservableCollection<MyType>() { new MyType() { Key = "1", Value = "One" }, new MyType() { Key = "2", Value = "Two" } };
            MyType = MyTypes[1];
        }

... etc.

<ListView
            SelectedItem="{Binding Path=SelectedCondition}"
            ItemsSource="{Binding Path=Conditions}"                 
            FontWeight="Normal"
            FontSize="11"                                
            Name="listview" Margin="0,32,0,0">
            <ListView.View>
                <GridView>
                    <GridViewColumn                           
                        Width="175"
                        Header="Type">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox                                       
                                    Width="150"
                                    SelectedValuePath="Key"
                                    DisplayMemberPath="Value"    
                                    SelectedItem="{Binding Path=MyType}"
                                    ItemsSource="{Binding Path=MyTypes}"
                                    HorizontalAlignment="Center" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
        <Button Content="Move up"
                Command="{Binding MoveUpCommand}"
                 />

0voto

Daniel Points 874

Intervertissez ces lignes :

SelectedItem="{Binding Path = SelectedCondition}" 
ItemsSource="{Binding Path = Conditions}" 

ItemSource doit se trouver avant SelectedItem.

0voto

Amsakanna Points 4161

Avez-vous essayé ItemsSource="{Binding Conditions}"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X