2010-06-16 8 views
2

J'ai créé une ObservableCollection dans le code derrière un contrôle utilisateur. Il est créé lorsque les charges de fenêtre:WPF ObservableCollection dans xaml

private void UserControl_Loaded(object sender, RoutedEventArgs e) 
    { 
     Entities db = new Entities(); 
     ObservableCollection<Image> _imageCollection = 
     new ObservableCollection<Image>(); 

     IEnumerable<library> libraryQuery = 
     from c in db.ElectricalLibraries 

     select c; 

     foreach (ElectricalLibrary c in libraryQuery) 
     { 
      Image finalImage = new Image(); 
      finalImage.Width = 80; 

      BitmapImage logo = new BitmapImage(); 
      logo.BeginInit(); 
      logo.UriSource = new Uri(c.url); 
      logo.EndInit(); 

      finalImage.Source = logo; 

      _imageCollection.Add(finalImage); 

     } 

    } 

je dois obtenir le ObservableCollection d'images qui sont créées en fonction de l'URL enregistrée dans une base de données. Mais je besoin d'un ListView ou autre ItemsControl de se lier à elle dans le fichier XAML comme ceci:

Mais je ne peux pas comprendre comment passer le ObservableCollection au ItemsSource de ce contrôle. J'ai essayé de créer une classe et ensuite créer une instance d'une classe dans le fichier xaml mais cela n'a pas fonctionné. Dois-je créer une ressource statique en quelque sorte>

Toute aide sera grandement appréciée.

Répondre

4

Premièrement, ObservableCollection est une variable locale. Ce que vous devez faire est de l'avoir comme une variable globale privée et l'exposer avec une propriété publique. Vous pouvez utiliser l'interface INotifyPropertyChanged pour que les données d'image soient automatiquement mises à jour lorsque la collection elle-même change.

Dans votre code XAML, vous devez ensuite définir le DataContext sur vous-même et vous pouvez ensuite lier directement votre propriété publique à ItemsSource. Vous pouvez utiliser un ItemTemplate pour afficher les éléments d'une manière personnalisée.

Cheers, Adam

Exemple comme demandé:

En C#:

public MyWindowClass 
{ 
    public ObservableCollection<image> MyImageCollection 
    { 
    get; 
    set; 
    } 
} 

En XAML:

<UserControl 
... 
DataContext="{Binding RelativeSource={RelativeSource Self}}"> 

... 
<ListBox ItemsSource="{Binding MyImageCollection}" ItemTemplate="*yourtemplateresource*" /> 
... 

</UserControl> 

Maintenant, la raison pour laquelle je l'ai mentionné à l'aide INotifyPropertyChanged est que si vous essayez:

MyImageCollection = new ObservableCollection<image>(); 

Les éléments de la zone de liste ne seront pas mis à jour automatiquement. Avec un ObservableCollection, cependant, vous devez pas besoin d'implémenter INotifyPropertyChanged pour l'ajout de base et la suppression des éléments de liste.

+1

Techniquement correct, sauf si vous souhaitez ajouter plus de détails, et fixer un petit point - * ObservableCollection * implémente déjà * INotifyCollectionChanged * et * INotifyPropertyChanged * il n'est donc pas nécessaire de les réimplémenter/invoquer sur la propriété publique mentionnée. – slugster

+0

Merci de votre aide. Pourriez-vous fournir de petits extraits de code à titre d'exemple? – Enzomatric

+0

@slugster - désolé de ne pas être clair dans ma réponse. La raison pour laquelle j'ai mentionné INotifyPropertyChanged était purement pour mettre à jour la liste si la propre propriété publique de l'auteur était réinitialisée. Je n'aurais probablement pas dû ajouter cette information excédentaire ... @Cloverness - ajouter un exemple ... –

1

Vous devez définir le DataContext du UserControl à votre collection:

DataContext = _imageCollection 

Vous pouvez le faire dans la méthode UserControl_Loaded().

Ensuite, vous devez lier le ItemsSource du ListView dans le XAML:

<ListView ItemsSource="{Binding}"/> 

Le {Binding} est équivalent à {Binding .} qui se lie au DataContext du UserControl.Si vous avez besoin « plus de choses » dans votre DataContext vous pouvez plutôt créer une classe comme ceci:

class ViewModel : INotifyPropertyChanged { 
    public ObservableCollection Images { get { ... } } 
    ... 
} 

Utilisez cette classe pour la DataContext:

DataContext = new ViewModel(); 

Et remplacer la liaison à se lier à la propriété Images :

<ListView ItemsSource="{Binding Images}"/> 

vous pouvez ensuite ajouter une autre propriété à ViewModel:

class ViewModel : INotifyPropertyChanged { 
    public ObservableCollection Images { get { ... } } 
    public String Message { get { ... } set { ... } } 
    ... 
} 

et le lier à un contrôle:

<TextBlock Text="{Binding Message}"/> 

N'oubliez pas de déclencher l'événement PropertyChanged lorsque la propriété Message est changé en ViewModel. Cela mettra à jour l'interface utilisateur lorsque les propriétés du modèle de vue sont modifiées par le code.

+0

Merci beaucoup. Maintenant, j'ai un autre problème dans mon code. – Enzomatric