views:

330

answers:

2

Hi, I have created an ObservableCollection in the code behind of a user control. It is created when the window loads:

    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);

        }

    }

I need to get the ObservableCollection of images which are created based on the url saved in a database. But I need a ListView or other ItemsControl to bind to it in XAML file like this:

But I can't figure it out how to pass the ObservableCollection to the ItemsSource of that control. I tried to create a class and then create an instance of a class in xaml file but it did not work. Should I create a static resource somehow>

Any help will be greatly appreciated.

+3  A: 

Hi,

Firstly, the ObservableCollection is a local variable. What you need to do is have it as a private global variable and expose it with a public property. You can use the INotifyPropertyChanged interface to have the image data update automagically when the actual collection itself changes.

In your XAML, you then need to set the DataContext to self, and you can then directly bind your public property to the ItemsSource. You may want to use an ItemTemplate for displaying the items in a custom manner.

Cheers, Adam

Example as requested:

In C#:

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

In XAML:

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

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

</UserControl>

Now, the reason that I mentioned using INotifyPropertyChanged is that if you try:

MyImageCollection = new ObservableCollection<image>();

The items in the listbox will not automatically update. With an ObservableCollection, however, you do not need to implement INotifyPropertyChanged for basic addition and removal of list items.

AJ
Technically correct except you may want to add more detail, and fix one small point - *ObservableCollection* already implements *INotifyCollectionChanged* and *INotifyPropertyChanged* so there is no need to reimplement/invoke them on the public property you mention.
slugster
Thank you for help. Could you provide any small snipets of code as an example?
Enzomatric
@slugster - sorry to be unclear in my response. The reason I mentioned INotifyPropertyChanged was purely to update the list if the author's own public property was reinitialised. I probably shouldn't have added that surplus info...@Cloverness - adding example...
AJ
+1  A: 

You have to set the DataContext of the UserControl to your collection:

DataContext = _imageCollection

You can do that in the UserControl_Loaded() method.

Next you need to bind the ItemsSource of the ListView in the XAML:

<ListView ItemsSource="{Binding}"/>

The {Binding} is equivalent to {Binding .} which binds to the DataContext of the UserControl. If you need "more stuff" in your DataContext you can instead create a class like this:

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

Use this class for the DataContext:

DataContext = new ViewModel();

And replace the binding to bind to the Images property:

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

Then you can add another property to ViewModel:

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

And bind it to a control:

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

Remember to fire the PropertyChanged event when the Message property is changed in ViewModel. This will update the UI when view-model properties are changed by code.

Martin Liversage
Thanks a lot. Now I have another problem in my code.
Enzomatric