Click here to Skip to main content
15,881,938 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more: , +
Hi,

i am writing a wpf applivation with the mvvm pattern. in my viewmodel, i receive the data asynchron over a wcf service:
C#
#region Construction
public  AddressViewModel()
{
    this.LoadAddress();
}

private async void LoadAddress()
{
    ServiceClient client = new ServiceClient();
    _address = await client.GetAddressByIdAsync(1);
}
#endregion

I bind the propertys in view like this:
XML
<TextBlock Grid.Column="1" Grid.Row="0"  Text="{Binding address1, IsAsync=True}"/>

The UI doesnt update automatically after the asynchron load. When i change a property via button (for example) the UI updates, so the problem must rely on the asynchron WCF-Call. I tried the following changes and they do the job but i think this is not good practice.
C#
private async void LoadAddress()
{
   ServiceClient client = new ServiceClient();
   _address = await client.GetAddressByIdAsync(1);
   RaisePropertyChanged("address1"); //Do this for each property?
}

Do i really have to RaisePropertyChange("propName") for each property of my class or is there a better, cleaner, more elegant way?

EDIT:
Normaly i raise the propertychangeevent in the setter like this:
C#
public string address1
{
   get { return Address.address1; }
   set
   {
       if (Address.address1 != value)
       {
           Address.address1 = value;
           RaisePropertyChanged("address1");
       }
   }
}
Posted
Updated 28-Dec-12 9:19am
v2

EDIT:
Sometimes you think to yourself... DOOOH :)
If someone is looking for this too:
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.propertychanged.aspx[^]

If you update your hole object, just do
C#
RaisePropertyChanged(null);
and you'll get all propertys updated.

Thx to db7uk for support.
 
Share this answer
 
Unfortunately yes. If you do not use something like Notify Property Weaver[^] you will need to raise the notify on each property change.

If you do not go down the automated route, I would really recommend setting your property value and then raising the changed event on the property setter rather than the method / void call your are doing. This helps keep code maintainable and in one place. Only my opinion but having raise property events in method calls can get messy unless really needed.
 
Share this answer
 
Comments
ChrisTopherus 28-Dec-12 15:16pm    
Hi db7uk,
i will have a look at the NotifyPropertyWeaver. For the second part of your solution:

that is the part i do not understand. i raise the propertychangedevent in the setter of the property. please look at my edit on the question. maybe there is an other problem... ???
db7uk 28-Dec-12 15:40pm    
You will need to raise the property changed event. This must be done in order for the UI to know a change has happened. Without it how would the UI know when to update itself? So you setter is correct. Interesting though, what is Address.address1? is this a model property within the viewmodel? So back to the question. You do need to raise the property changed event when something in your viewmodel property changes.
db7uk 28-Dec-12 15:43pm    
Added to that, consider using reflection property names. i.e. RaisePropertyChanged(() => address1). By strongly typing your property changed event will allow compile time support if your property name changes. Consider looking at Prism for Notifiable objects and delegate commands.
ChrisTopherus 28-Dec-12 16:13pm    
All servicefunctions/sql-statements etc. i use are "autogenerated" from a datacontract on the serverside. and the class Address has address1, address2, address3 to hold street and additional stuff... i know that this is not looking good^^
RaisePropertyChange(()=>address1) also works. The strange thing for me is, that the set of the propertys isn't called, when i update the whole object. with your info on your solution, i will call the raiseprop for all properties in the setter of the object:

#region Properties
public Address Address
{
get
{
return _address;
}
set
{
if(Address != value)
{
_address = value;
if(address1 != value.address1)
RaisePropertyChanged(() => address1);
if(address2 != value.address2)
RaisePropertyChanged(() => address2);
...
}
}
}
so i dont have it in method. do you think this is a good solution?
db7uk 28-Dec-12 16:50pm    
This is the better approach. I would host the Address class as a property and bind to that. i.e. text="{Binding Address.address1, IsAsync=True}" You would then only need to raise the changed event once. .i.e.
public Address Address
{
get
{
return _address;
}
set
{
if(Address != value)
{
_address = value;
RaisePropertyChanged(() => Address);
}
}
}

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900