Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Matthieu MEZIL

I love .Net

Abonnements

EF et WPF

Suite à une question que j'ai reçu par mail, j'ai développé ma première application WPF. Smile

Voici la question :

"J'utilise EF afin d'obtenir une extraction objet de ma BDD. Pour simplifier disons que j'ai une base COllège, avec une table Classe et une table élève.

Les élèves ne pouvant appartenir qu' à une Classe. J'ai crée en WPF, 2 fenêtre pour ajouter des classes et ajouter des élèves.

 

Dans la fenêtre des élèves j'ai une combo qui affiche les classes disponibles. Et je souhaitais que les items de cette combo, soient binder automatiquement à mon objet CollegeEntities. Hélas CollegeEntities.Classes ne dérive pas de ObservableCollection<T> et du coup lorsque je créé via ma fenêtre d'édition une nouvelle Classes, mon objet Combo n'est pas mise à jour.

 

Est-ce possible aujourd'hui avec EF de DataBinder automatiquement les listes d'Entities généré par EF ?"

Le premier point est le fait que les collections d'entitésObjectQuery<T> n'implémente pas INotifyCollectionChanged (en effet c'est cette interface qui permet à un contrôle dont la DataSource est un ObservableCollection<T> de se raffraîchir).

De plus, l'ObjectQuery ne renverra pas les nouvelles Classes tant que celles-ci ne seront pas persistées en base avec le Context.SaveChanges().

Donc comment faire ?

Tout simplement passé par une classe intermédiaire :

public class ContextEntitiesLoaded<T> : IEnumerable<T>, INotifyCollectionChanged

{

    private ObjectContext _context;

    private EntityState _states = EntityState.Added | EntityState.Modified | EntityState.Unchanged;

 

    public ContextEntitiesLoaded(ObjectContext context)

    {

        _context = context;

        _context.ObjectStateManager.ObjectStateManagerChanged += (sender, e) =>

        {

            if (e.Element is T)

                switch (e.Action)

                {

                    case CollectionChangeAction.Add:

                    case CollectionChangeAction.Remove:

                        if (e.Element is T)

                            OnNotifyCollectionChanged();

                        break;

                }

        };

    }

 

    public EntityState States

    {

        get { return _states; }

        set { _states = value; }

    }

    public Func<T, object> SortExpression { get; set; }

 

    protected virtual void OnNotifyCollectionChanged()

    {

        if (CollectionChanged != null)

            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));

    }

 

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()

    {

        var q = _context.ObjectStateManager.GetObjectStateEntries(States).Select(se => se.Entity).OfType<T>();

        if (SortExpression != null)

            q = q.OrderBy(SortExpression);

        return q.GetEnumerator();

    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

    {

        return GetEnumerator();

    }

    #endregion

 

    #region INotifyCollectionChanged Members

    public event NotifyCollectionChangedEventHandler CollectionChanged;

    #endregion

}

Ensuite, il suffit de récupérer les classes dans le context et de le binder avec la combo :

public partial class Window1 : Window

{

    public Window1()

    {

        InitializeComponent();

        ObjectDataProvider odp = this.FindResource("maSource") as ObjectDataProvider;

        if (odp != null)

        {

            foreach (var c in NorthwindEntities.Instance.Categories); // to load the categories on the context

            odp.ObjectInstance = new ContextEntitiesLoaded<Category>(NorthwindEntities.Instance) { SortExpression = c => c.CategoryName };

        }

    }

    [...]

}

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Publié vendredi 29 août 2008 21:35 par Matthieu MEZIL

Classé sous : , , ,

Commentaires

# re: EF et WPF @ vendredi 29 août 2008 23:38

Matthieu, j'y connais rien en EF mais pourquoi ne pas avoir fait, tout simplement ceci (mais p-e que cela ne marche pas) ?

odp.ObjectInstance = new ObservableCollection<Category>(NorthwindEntities.Instance.Categories);

(éventuellement, en appellant ToList() sur NorthwindEntities.Instance.Categories)

Thomas LEBRUN

# re: EF et WPF @ samedi 30 août 2008 13:20

Répondu dans un nouveau post.

Matthieu MEZIL

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le il y a 1 heure et 24 minutes

- [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le il y a 2 heures et 38 minutes

- SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le il y a 16 heures et 17 minutes

- [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le il y a 17 heures et 14 minutes

- MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le il y a 17 heures et 29 minutes

- Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

- C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

- Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15

- SharePoint : Gestion des Erreurs 6398, 7076 et 6482 par Blog Technique de Romelard Fabrice le 07-02-2009, 11:53

- EF avec WPF par Matthieu MEZIL le 07-02-2009, 10:18