0

In the code below, the UnitOccupierDetails collection binds correctly but the OwnersCountString doesn't. Can anyone explain why? This code is in my ViewModel:

private void BindSelectedStructure(object param) 
    { 
        UnitOccupierDetails.Clear(); 
        Structure selectedStructure = (Structure)param; 
        this.SelectedStructure = selectedStructure; 

        int StructureID = selectedStructure.IDStructure; 
        loadOwners = context.Load<UserOccupier>(context.GetUnitOccupierDetailsQuery(StructureID), OwnersLoadedCallback, false); 
    } 

    private void OwnersLoadedCallback(LoadOperation<UserOccupier> op) 
    { 
        int Counter = 0; 
        foreach (var item in op.Entities) 
        { 
            Counter++; 
            UnitOccupierDetails.Add(item as UserOccupier); 
        } 

        OwnersCountString = "Owners(" + Counter.ToString() + ")"; 
    }

And the XAML:

     <TextBlock Text='{Binding OwnersCountString,Source={StaticResource ViewModel},Mode=OneWay}'></TextBlock

OwnersCountStringProperty:

private string _ownersCountString;
    public string OwnersCountString
    {
        get { return _ownersCountString; }
        set { _ownersCountString = value; RaisePropertyChanged("OwnersCountString"); }
    }
Cœur
  • 37,241
  • 25
  • 195
  • 267
Greg
  • 2,654
  • 3
  • 36
  • 59
  • 1
    Yet another comment. (Seriously, please try and give your questions more descriptive titles. They don't all appear sequentially, so it's hard to know what the question will be about from the home page.) – Cody Gray - on strike Jul 25 '11 at 16:19
  • That ain't MVVM, and `public string OwnersCountString {get;set;}` won't work as you expect. Also, that's a matter for the UI and should be handled with a converter and/or a StringFormat in the binding. Oh, and you should check the framework guidelines for naming. Also, please forgive my failure to make this seem helpful. –  Jul 25 '11 at 16:20
  • Point taken Cody. Will, the code I posted is obviously only a part of the MVVM. OwnerCountString raises the property changed event as required. BindSelectedStructure is the ICommand call and works perfectly. The ONLY thing that isnt working is setting the STRING property. That shouldnt need a converter should it? Even if I use a plain string (without Counter.ToString()), the binding doesnt work. – Greg Jul 25 '11 at 17:22
  • Please see my updated code post with the property code shown. – Greg Jul 25 '11 at 17:31
  • Will, any chance of you adding advice or suggestions or are you done? – Greg Jul 25 '11 at 18:32
  • Post your entire viewmodel, and the XAML defining the StaticResource "ViewModel". – Claus Jørgensen Jul 25 '11 at 19:12
  • You have to use @Will in order to notify him that you've replied. I just happened to leave the tab open. – Cody Gray - on strike Jul 26 '11 at 07:54
  • @greg: asssuming a public collection property (ObservableCollection, most properly) named `Owners` the binding would be `{Binding Owners.Count, StringFormat='Owners({0})'` –  Jul 26 '11 at 11:18

1 Answers1

1

Your callback is not occurring on the UI thread. That means that the change is happening, but the UI has not updated itself on the thread that displays changes.

Here is our example from another of my answers. Our version of SendPropertyChanged (replace your RaisePropertyChanged) makes sure any code is executed on the UI thread:

protected delegate void OnUiThreadDelegate();

public event PropertyChangedEventHandler PropertyChanged;

public void SendPropertyChanged(string propertyName)
{
    if (this.PropertyChanged != null)
    {
        this.OnUiThread(() => this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)));
    }
}

protected void OnUiThread(OnUiThreadDelegate onUiThreadDelegate)
{
    if (Deployment.Current.Dispatcher.CheckAccess())
    {
        onUiThreadDelegate();
    }
    else
    {
        Deployment.Current.Dispatcher.BeginInvoke(onUiThreadDelegate);
    }
}
Community
  • 1
  • 1
iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
  • HiTech, thanks for your reply. I suspected this might have something to do with threading. How should I have gone about testing the thread. Is this best done with Fiddler? – Greg Jul 26 '11 at 09:19
  • Fiddler has nothing to do with Silverlight threads. It shows data communications to/from the browser. You just need to know that certain operations do not callback on the UI thread (so safer to always call property change events on the UI thread). – iCollect.it Ltd Jul 26 '11 at 09:50
  • OK - last question. If my OwnersLoadedCallback was on the UI thread, how come the UnitOccupierDetails collection was updated correctly? Is is that I was setting another property (OwnerCountString) in that method and the UI thread was busy with OwnersOccupierDetails? Sorry, threading is new to me :-) – Greg Jul 26 '11 at 10:33
  • I can only guess that the collection events cause a more significant change to the control state which is subsequently rendered (textblock are pretty dumb). I guess my only question is: did the fix work in your specific instance? – iCollect.it Ltd Jul 26 '11 at 11:25
  • I implemented your code in my ViewModelBase and changed the RaisePropertyChanged to SendPropertyChanged but unfortunately it has not resolved the problem. In the SendPropertyChanged method, this.PropertyChanged is always returning null. – Greg Jul 26 '11 at 11:29
  • If PropertyChanged is null it is the binding that is not working. Can you provide enough code and VM to check and reproduce the problem? Typoes are a common cause. – iCollect.it Ltd Jul 26 '11 at 11:36
  • HiTech - found the problem on the ViewModelBase. Although the PropertyChangedEventHandler was declared, the class wasnt inheriting from INotifyPropertyChanged. I added this and everything (including your code) is working as expected. Thanks for the assistance and code. – Greg Jul 26 '11 at 12:18