Enzomatric
Enzomatric

Reputation: 497

WPF ObservableCollection in xaml

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.

Upvotes: 2

Views: 5478

Answers (2)

Martin Liversage
Martin Liversage

Reputation: 106926

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.

Upvotes: 1

AJ.
AJ.

Reputation: 1671

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.

Upvotes: 4

Related Questions