9
votes

WPF Combobox réinitialise l'élément sélectionné lorsque l'élément-source change

considérer comme suit XAML: xxx

globaldata.comanies est une collection ( ienumerable ) des entreprises; Cette collection peut être rechargée sur fond (il est téléchargé à partir d'un service Web). Lorsque cela se produit, ComboBox recharge correctement les éléments par liaison. Cependant comme effet secondaire, il réinitialise également l'élément sélectionné!

J'ai utilisé le réflecteur pour inspecter les sources de la boîte déroulante et apparemment, il s'agit de comportement prévu.

y a-t-il "bien «Comment se déplacer ça? Ce que je veux réaliser, c'est que si l'utilisateur sélectionne "Société a" et recharger la liste des entreprises par la suite, alors "Société A" Séjours sélectionnés (en supposant que c'est dans la nouvelle liste).


0 commentaires

4 Réponses :


1
votes

hmm, je ne sais pas s'il s'agit d'une "belle" façon, mais si vous pouvez accéder à l'élément sélectionné avant que le rechargement ne se produise, vous pouvez l'enregistrer (ou sa clé ou quelque chose), et la sélectionner de manière programmative après La recharge est terminée.

maquette rapide: p> xxx pré>

mais je suppose que vous voulez dire une autre manière que ce manuel fonctionne?
J'espère que cela vous aidera de toute façon ... p>

Mise à jour forte>

Ok je vois, d'un fil de fond.
Utilisez-vous une ICOLLECTIONVIEW pour lier votre ComboBox aussi? Si tel est le cas, vous pouvez utiliser la propriété actuelle pour conserver une référence. J'ai fait une maquette rapide et cela fonctionne sur ma configuration. Cela suppose que vous avez une référence à votre UI: p>

xaml em> p> xxx pré>

Voir / ViewModel EM> P>

public partial class Window1 : Window {
   public Window1() {
        InitializeComponent();
        this.DataContext = new ViewModel(this);
   }
}

public class ViewModel
{
    private readonly Window1 window;
    private ObservableCollection<Item> items;
    private ICollectionView view;

    public ViewModel(Window1 window) {
        this.window = window;
        items = new ObservableCollection<Item>
            {
                new Item("qwerty"),
                new Item("hello"),
                new Item("world"),
            };

        view = CollectionViewSource.GetDefaultView(items);
    }

    public ObservableCollection<Item> Items { get { return items; } }

    public ICommand UpdateCommand {
        get { return new RelayCommand(DoUpdate); }
    }

    public Item SelectedItem { get; set; }

    private void DoUpdate(object obj) {
        var act = new Func<List<Item>>(DoUpdateAsync);
        act.BeginInvoke(CallBack, act);
    }

    private List<Item> DoUpdateAsync() {
        return new List<Item> {
                new Item("hello"),
                new Item("world"),
                new Item("qwerty"),
            };
    }

    private void CallBack(IAsyncResult result) {
        try {
            var act = (Func<List<Item>>)result.AsyncState;
            var list = act.EndInvoke(result);

            window.Dispatcher.Invoke(new Action<List<Item>>(delegate(List<Item> lst) {
                                                                    var current = lst.Single(i => i.Name == ((Item)view.CurrentItem).Name);
                                                                    Items.Clear();
                                                                    lst.ForEach(Items.Add);
                                                                    view.MoveCurrentTo(current);
                                                                }), list);

        } catch(Exception exc){ Debug.WriteLine(exc); }
    }
}

public class Item {
    public Item(string name) {
        Name = name; 
    }
    public string Name { get; set; }
}


2 commentaires

Le problème est que Doreload () est effectué sur fond par une classe qui n'a aucune idée de l'interface graphique. L'interface graphique est notifiée sur les nouvelles valeurs via la liaison et l'inotifyPropertychangned.


Si la description de la valeur sélectionnée peut changer lors de l'actualisation, ajoutez "My_Combo.Selectedindex = -1" après la charge Doreload (). Cela entraînera une description affichée à rafraîchir lorsque l'index sélectionné est mis à jour après la réinitialisation de l'élément sélectionné.



4
votes

Peut-être que vous pouvez utiliser observablecollection au lieu de votre ienumerable ? Ensuite, sur changements d'arrière-plan, vous ne ferez que ajouter / supprimer des éléments qui sont nouveaux / absents dans la nouvelle liste, l'élément sélectionné devrait rester, à moins qu'il ne soit supprimé par le changement.

Vous pouvez mettre à jour votre collection observable dans un fil séparé avec un petit hack autour de .


2 commentaires

Cela pourrait être la solution, bien que ce ne soit pas aussi agréable / facile que je voudrais: - |


Il n'est probablement pas nécessaire de mettre à jour la collection à partir du fil d'arrière-plan. Obtenez la collection actuelle du service Web en arrière-plan, puis (en supposant que vous utilisez un ouvrier d'arrière-plan) Mettez à jour le Observablecollection dans l'événement d'exécutionCommandé.



0
votes

Comme l'a souligné Yacoder, cela a trait à l'égalité des objets. Tant que vous liez la sélection de SelectValue au lieu de SELECTELITEM, vous pouvez définir les élémentsSource en tant que collection de type anonyme. Ensuite, ce problème ne se produira pas (et il est également plus rapide si vous devez lire les valeurs d'une base de données).


0 commentaires

11
votes

Veuillez essayer avec le code suivant. Activez la propriété suivante à la liste déroulante

IssynchronizedWithCurrentItem = "vrai"


0 commentaires