Question

Je lie un ItemsControl à un EntitySet dans une application WPF. Il n'agit pas comme prévu, cependant. ItemsControl se comporte comme s'il mettait en cache le contenu de EntitySet entre les liaisons!

Voici le code simplifié :

L'entité:

public partial class Item : INotifyPropertyChanging, INotifyPropertyChanged
{
    private EntitySet<Item> _Children;
    public EntitySet<Item> Children {get{return _children;}}
    /*...*/    
}

Ma classe partielle:

public partial class Item
{
    public void RemoveChild(Item child)
    {
        Children.Remove(child);
        // this finds PropertyChanged; defined in the Entity class
        SendPropertyChanged("Children");
    }
}

L'interface utilisateur:

<ItemsControl
    Name="ItemChildren"
    Background="CornflowerBlue"
    ItemsSource="{Binding Children}">
    <ItemsControl.ItemTemplate>
        <DataTemplate
            DataType="{x:Type d:Item}">
            <DockPanel>
                <TextBlock
                    Text="{Binding Name}/>
            </DockPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Code illustrant le comportement (supposons que > 2 éléments ayant chacun un enfant):

this.ScrewyItem = Db.Items.First();
this.DataContext = ScrewyItem;
return;

Plus tard, je retire l'enfant de l'entité:

ScrewyItem.RemoveChild(ScrewyItem.Children.First());
return;

Après l'exécution de ce code, l'interface utilisateur ne se met pas à jour et l'élément est réputé avoir tous les enfants. Notez que cette méthode appelle NotifyPropertyChanged, les liaisons doivent donc être mises à jour!

Plus tard, nous retirons cet élément des liaisons de l'interface utilisateur:

this.DataContext = Db.Items.Last(); //different item
return;

Et liez-le ensuite à l'interface utilisateur plus tard

this.DataContext = ScrewyItem;

Vous supposeriez qu'au moins à ce stade, l'interface utilisateur afficherait la liste d'enfants correcte. Ce n'est pas le cas , cependant! La liste identique des enfants est identique à celle indiquée à l'origine!

Ce qui est encore plus bizarre, si je mets un point d'arrêt sur mon accesseur Children, je peux voir que la liste est accessible lorsque je me rapproche de l'interface utilisateur et la liste ne contient pas l'enfant que j'ai supprimé.

La seule façon dont je peux voir que l'interface utilisateur pourrait le faire est si le contenu de la collection Children est mis en cache entre les liaisons.

Que se passe-t-il ici? Qu'est-ce qui me manque ???

Était-ce utile?

La solution

J'ai trouvé une solution pour cela. C'est un peu nul.

Je peux envelopper la collection Children dans une BindingList:

public IBindingList BindableChildren
{
    get
    {
        return new BindingList<Item>(Children);
    }
}

puis modifiez ma méthode RemoveChild comme suit:

this.Children.Remove(arg);
SendPropertyChanged("BindableChildren");

L’UI met immédiatement à jour la liste et cesse de présenter le comportement de la mise en cache.

La question demeure: WTF? et Y a-t-il un autre moyen?

Autres conseils

Je n'en suis pas sûr, mais peut-être que ItemsControl écoute les événements de IBindingList ou INotifyCollectionChanged et non INotifyPropertyChanged .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top