views:

181

answers:

4

I am new to Silverlight, and have an issue with binding.

I have a class ItemsManager, that has inside its scope another class Item.

class ItemsManager
{
...
 class Item : INotifyPropertyChanged
 {
  ...
  private BitmapImage bitmapSource;
  public BitmapImage BitmapSource
  {
   get { return bitmapSource; }
   set 
   { 
    bitmapSource = value; 
    if(PropertyChanged != null )PropertyChanged("BitmapSource") 
   }
  }            
 }
}

I do the following in code to test binding:

 {
  ItemsManager.Instance.AddItem("123");
  //Items manager started downloading item visual 
  //part (in my case bitmap image png)

  Binding b = new Binding("Source");
  b.Source = ItemsManager.Instance.GetItem("123").BitmapSource;
  b.BindsDirectlyToSource = true;

  Image img = new Image();
  img.SetBinding(Image.SourceProperty, b);
  img.Width = (double)100.0;
  img.Height = (double)100.0;

  LayoutRoot.Children.Add(img);
}

Once image is loaded, image doesn't appear. Though, if I set directly after image has been loaded its source, it displays well.

I also noticed that PropertyChanged("BitmapSource") never fires, because PropertyChanged is null, like Image never binded to it.

I am looking forward to hearing from you!

A: 

Hi! PropertyChanged("BitmapSource") fires in case of two-way binding. I.e. if you use two way binding and then manually change image source, like

img.Source = new BitmapImage(new Uri("http://...."));

the property changed event would fire.

As for the image appearance, it seems you bind data in wrong way. Try declarative bindings.

kate n
Well, basically I have implemented INotifyPropertyChanged interface just to try why binding is not working, I really need just one-way binding.I don't change image manually, because it works this way. I just want to have Image.Source being set automatically, when property BitmapSource will arrive, and will change from null to real BitmapImage object.
Alexander K
A: 

There are several things wrong with this code:-

  • You've bound directly to the BitmapImage exposed by the BitmapSource property so you've taken your nested Item class out of the picture anyway.
  • Also for the property setter to be called you would need something to assign a value to the Image elements Source property and your binding would need to be in two way mode.
  • Your binding object creation is confused, it specifies a path (which is wrong anyway) but then binds direct to source.

Hence your code would need to look like this:-

Binding b = new Binding("BitmapSource"); 
b.Source = ItemsManager.Instance.GetItem("123"); 
b.Mode = BindingMode.TwoWay;

Now when a new BitmapImage is assigned the Image Source property your setter code should run. However it should be born in mind that the this property is of the more general type ImageSource. Hence this code will break if another derivative of ImageSource is assigned instead.

One other thing which may be a problem, I can't recall of the top of my head whether Silverlight supports binding to nested types. You might need to bring your Item class out of ItemsManager and give it a more specific name like ManagedItem.

AnthonyWJones
Thanks man, nice info. Some pieces got screwed up because I rewrote a couple times.
Alexander K
A: 

First, do not bind to BitmapImage unless you have a good reason. Binding to a string is good enough. The implicit conversion will happen automatically. Second, use declaritive binding. Programatic creation and binding is a real mess. Third, only implement INotifyPropertyChanged if you need to send changes of that property to the UI.

You are likely over complicating your situation with all this extra code.

Brian Genisio
Okay, thanks. Seems like it is really easier to make direct assignment in code, than auto binding.
Alexander K
A: 

Thanks for explanations. However, I don't need a TwoWay binding. Just one way, once ItemsManager downloads Item image, it should be automatically updated in the Image control.

So, I changed my code to this:

ItemsManager.Instance.AddItem("123");

Binding b = new Binding("BitmapSource");
b.Source = ItemsManager.Instance.GetItem("123");

Image img = new Image();
img.SetBinding(Image.SourceProperty, b);
img.Width = (double)100.0;
img.Height = (double)100.0;

LayoutRoot.Children.Add(img);

I also took Item out of ItemsManager scope, so it is now in its own class file, but image still stays empty, even though bitmap image arrives, and changes in BitmapSource property of Item object.

Alexander K
The content of this "Answer" is not actually an answer but a progress update. You should modify your question using the edit function and place this content on the end of your question.Once you've done that you can delete this answer.
AnthonyWJones