2012-02-08 8 views
0

Je n'arrive pas à faire fonctionner une liaison ListBox comme prévu. J'essaye actuellement de lier un ListBox à un ObservableCollection exposé par singleton d'articles. Les éléments sont eux-mêmes une classe distincte. À l'heure actuelle, je suis RELIURE comme ceci:ListBox lié à ObservableCollection ne se met pas à jour

<Window x:Class="toxySharp.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:classes="clr-namespace:MyApplication.Classes" 
     Title="MainWindow" Height="325" Width="400" 
     DataContext="{Binding Source={x:Static local:SingletonClass.Instance}}"> 

     <Grid x:Name="LayoutRoot"> 
      <ListBox x:Name="lstMyList" ItemsSource="{Binding Path=Objects, Mode=TwoWay}" DisplayMemberPath="Name" /> 
     </Grid> 
</Window> 

Mon singleton est une implémentation de base comme celui-ci:

public class SomeObject : INotifyPropertyChanged 
{ 
    private Int32 m_vId; 
    private String m_vName; 

    public SomeObject() { } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String propName) 
    { 
     if (this.PropertyChanged != null) 
     { 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
     } 
    } 

    public Int32 Id 
    { 
     get { return this.m_vId; } 
     set { this.m_vId = value; NotifyPropertyChanged("Id"); } 
    } 

    public String Name 
    { 
     get { return this.m_vName; } 
     set { this.m_vName = value; NotifyPropertyChanged("Name"); } 
    } 
} 

public class SingletonClass : INotifyPropertyChanged 
{ 
    private static SingletonClass m_vInstance; 
    private ObservableCollection<SomeObject> m_vObjects; 

    private SingletonClass() 
    { 
     this.m_vObjects = new ObservableCollection<SomeObject>(); 
     for (int x = 0; x < 255; x++) 
      this.m_vObjects.Add(new SomeObject() { Id = x, Name = String.Format("{0} - new object", x) }); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String propName) 
    { 
     if (this.PropertyChanged != null) 
     { 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
     } 
    } 

    public static SingletonClass Instance 
    { 
     get 
     { 
      if (m_vInstance == null) 
       m_vInstance = new SingletonClass(); 
      return m_vInstance; 
     } 
    } 

    public ObservableCollection<SomeObject> Objects 
    { 
     get { return this.m_vObjects; } 
     set { this.m_vObjects = value; NotifyPropertyChanged("Objects"); } 
    } 
} 

Actuellement, les travaux de liaison au démarrage. L'application liera et affichera correctement les noms de chaque objet. Par exemple ceci est une application de test faire la même mise en œuvre: enter image description here

Dans ma principale application réelle que j'ai appelés méthodes async (substance Socket BeginConnect, BeginSend, etc.) qui utilisent des callbacks qui peuvent mettre à jour la collection. (C'est une liste de lecteurs donc quand certains paquets sont reçus la liste est mise à jour avec leurs données.)

Mon problème est quand la collection est mise à jour dans l'un des rappels asynchrones qu'elle ne met pas à jour dans la liste. Les données de collecte sont mises à jour correctement, la définition d'une rupture dans le code principal n'importe où montre la collection en cours de mise à jour, mais la liste ne se met jamais à jour pour refléter les modifications. Donc, il reste juste à dire la même chose, peu importe quoi.

Ai-je oublié quelque chose?

J'ai aussi essayé d'utiliser une CollectionViewSource pour permettre le filtrage et cela a le même problème.

== == EDIT

J'ai trouvé le problème qui se trouve dans le singleton avec la façon dont la collection est initialisé. Au lieu d'utiliser le membre de copie interne lors de l'initialisation de la collection, j'ai dû utiliser la propriété exposée pour lui permettre de mettre à jour l'interface utilisateur.

Donc, en utilisant ce qui suit le fixe:

private SingletonClass() 
{ 
    this.Objects = new ObservableCollection<SomeObject>(); 
    for (int x = 0; x < 255; x++) 
     this.Objects.Add(new SomeObject() { Id = x, Name = String.Format("{0} - new object", x) }); 
} 

Cependant maintenant que la liste des travaux de liaison que je veux être en mesure de filtrer cette fonction sur une autre propriété à l'intérieur de la classe d'objet. (Dans l'exemple SomeObject). J'ai un booléen indiquant si l'objet est actif. Essayer de lier une CollectionViewSource me ramène aux problèmes de non mise à jour. Donc, y a-t-il un moyen de filtrer ceci manuellement et de garder l'interface utilisateur mise à jour?

Répondre

0

UpdateSourceTrigger = PropertyChanged manque

<ListBox x:Name="lstMyList" ItemsSource="{Binding Path=Objects,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" DisplayMemberPath="Name" /> 
+1

Cela ne fait rien du tout, ItemsSource est jamais changé sur la cible, il ne se propage pas à la source dans tous les cas. –

+0

si im compréhension de l'OP correctement, alors c'est la source qui est en cours de mise à jour, mais la vue ne le voit pas. qui doit avoir un updatedsourcetrigger = propertychanged pour le réparer. Si cela ne fait rien, laissez-moi savoir quelle est votre définition de «source». dans ma tête, cela signifie que la collection observabl sur le modèle de vue – Anton

+2

Non, 'UpdateSourceTrigger' va ** dans l'autre sens **, par ex. dans un TextBox, quand quelqu'un entre un texte, il détermine si la source à laquelle Text est lié doit être mise à jour à chaque frappe. 'ItemsControls' ne modifie pas la propriété' ItemsSource' et ne peut pas non plus être modifiée par l'utilisateur, 'UpdateSourceTrigger' ne fera jamais rien. –

2

Mon problème est quand la collection est mis à jour dans l'un des callbacks async il ne met pas à jour sur la liste.

Eh bien c'est le problème n'est pas! Les collections observables ne sont pas thread-safe. Vous devez les faire comme ça.

Aucun mode de liaison TwoWay ou UpdateSourceTrigger=PropertyChanged aidera dans ce cas que le problème réside multi threading dans votre code ...

Utilisez cette implémentation personnalisée de fil en toute sécurité et de collecte plus rapide observable pour votre facilité ...En ce qui concerne l'interface que INotifyPropertyChanged concerne

Fast performing and thread safe observable collection

, son « PropertyChanged event is automatically dispatched to the UI thread. So any multithreaded context updating the properties of a class that implements INotifyPropertyChanged` mettra à jour l'interface graphique.

Permettez-moi de savoir si cela aide,

+0

Il n'y a pas de problèmes de thread, je m'assure que tout ce qui est dans les callbacks est invoqué sur le thread principal pour s'assurer que les problèmes de thread ne se produisent pas. – atom0s

+0

Pouvez-vous montrer ce code? –

+0

Edité la question principale, j'ai trouvé la cause du problème de mise à jour. Mais maintenant, la question est de savoir comment le trier, car la liaison à une CollectionViewSource provoque à nouveau les problèmes de mise à jour. – atom0s

Questions connexes