Niax

I'm having some issues with data binding to an collection which is within my code, am I doing everything correctly

XAML:

<Window.Resources>

<CollectionViewSource

Source="{Binding Source={x:Static Application.Current}, Path=contacts}"

x:Key="contactsDataBind"/>

<SolidColorBrush Color="#80808080" x:Key="Bg"/>

<DataTemplate x:Key="contactTemplate" DataType="{x:Type MSNClient:Contact}">

<StackPanel Orientation="Vertical">

<StackPanel Orientation="Horizontal">

<TextBlock Name="tbDisplayName" Text="{Binding Path=DisplayName}"/>

<TextBlock Name="tbStatus"

Text="{Binding Path=Status}"/>

</StackPanel>

<TextBlock Name="tbPersonalMessage"

Text="{Binding Path=PersonalMessage}" />

</StackPanel>

</DataTemplate>



</Window.Resources>


Code:

ObservableCollection<Contact> DummyContactList
{
get

{
Contact dummyContact = new Contact();

ObservableCollection<Contact> dummy = new ObservableCollection<Contact>();

dummy.Add(dummyContact);

return dummy;

}

}



ObservableCollection<Contact> contacts

{

get

{

if (SignedIn)

return chatClient.ContactList;

else

return DummyContactList;

}

set { chatClient.ContactList = value; }

}





Re: Windows Presentation Foundation (WPF) Data Binding to an Collection

Sam Bent - MSFT

1. Make the 'contacts' property public. Binding cannot see private properties.

2. The setter for 'contacts' changes the value of the property, but doesn't notify anyone. To fix this, implement INotifyPropertyChanged on your class (the one that contains the 'contacts' property), and make the setter raise the PropertyChanged event with PropertyName argument 'contacts'.

3. The DummyContactList property returns a different value every time you call its getter. This is bad form - it's better to allocate the dummy object once and return it every time the getter is called. Otherwise the property looks like its value is changing without any notification, which can confuse the data binding clients.

4. Even better would be to use the standard pattern for properties that return a collection value. Which is: make the property read-only (no setter) and initialize its value to an empty collection. Use an ObservableCollection as the collection type, so that the data binding clients get notified as you add/remove items to the collection. If you want to keep clients from changing the collection, but you still want to make changes internally, use a ReadOnlyObservableCollection initialized from an internal ObservableCollection and make your internal changes to the ObservableCollection.






Re: Windows Presentation Foundation (WPF) Data Binding to an Collection

Niax

Apologies, I should have shown deeper into the code.

This is the class Contact:

public class Contact : INotifyPropertyChanged

{

private string eMailAddress;

private string displayName;

private List<int> groups;

private Status status;

private List<ContactLists> lists;

private string guid;

private string personalMessage;



public string EMailAddress

{

get { return eMailAddress; }

set { eMailAddress = value; OnPropertyChanged("EMailAddress"); }

}

public string DisplayName

{

get { return displayName; }

set { displayName = value; OnPropertyChanged("DisplayName"); }

}

public List<int> Groups

{

get { return groups; }

set { groups = value; OnPropertyChanged("Groups"); }

}

public Status Status

{

get { return status; }

set { status = value; OnPropertyChanged("Status"); }

}

public List<ContactLists> Lists

{

get { return lists; }

set { lists = value; OnPropertyChanged("Lists"); }

}

public string GUID

{

get { return guid; }

set { guid = value; OnPropertyChanged("GUID"); }

}

public string PersonalMessage

{

get { return personalMessage; }

set { personalMessage = value; OnPropertyChanged("PersonalMessage"); }

}



protected void OnPropertyChanged(string info)

{

PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)

handler(this, new PropertyChangedEventArgs(info));

}

public event PropertyChangedEventHandler PropertyChanged;

}

And this is the collection which contacts is linking to:

public ObservableCollection<Contact> ContactList = new ObservableCollection<Contact>();








Re: Windows Presentation Foundation (WPF) Data Binding to an Collection

Sam Bent - MSFT

All well and good, but I think the problem is not about the collection, but rather about the 'contacts' property itself. Is it a public property on your application class

When you run your app under the debugger, do any trace messages appear in the output window






Re: Windows Presentation Foundation (WPF) Data Binding to an Collection

Niax

The contacts property is now public, error in output window:
System.Windows.Data Error: 35 : BindingExpression path error: 'contacts' property not found on 'object' ''App' (HashCode=59109011)'. BindingExpression:Path=contacts; DataItem='App'
(HashCode=59109011); target element is 'CollectionViewSource' (HashCode=42659827)' target property is 'Source' (type 'Object')







Re: Windows Presentation Foundation (WPF) Data Binding to an Collection

Sam Bent - MSFT

Which class defines the 'contacts' property This message is saying that it's not the 'App' class.




Re: Windows Presentation Foundation (WPF) Data Binding to an Collection

Niax

The contacts property is within the class Window1



Re: Windows Presentation Foundation (WPF) Data Binding to an Collection

Sam Bent - MSFT

The binding's source is the current Application, an object of type App. But the property belongs to an object of type Window1. No surprise that it cannot find the property. You have two choices: (a) move the property to the App class, or (b) change the binding's source to refer to Window1.

I'm sure you can do (a) - just move the code to App.xaml.cs. If this isn't appropriate, you can do (b) by replacing the binding's Source attribute with a pointer to Window1; here's one way to do that:

<Window ... Name="myWindow" ...>

<CollectionViewSource ... Source="{Binding ElementName="myWindow", Path=contacts}" .../>






Re: Windows Presentation Foundation (WPF) Data Binding to an Collection

Niax

This fixes the problem with the binding - however, there is now a problem in that the thread which populates the collection won't work, because it is not the owner of the ObservableCollection<Contact>

Should I set up some helper methods to deal with the functions I need to access - or is there a better way around this


Edit: Apologies, I forgot to say thank you :D




Re: Windows Presentation Foundation (WPF) Data Binding to an Collection

Sam Bent - MSFT

Right - if an ObservableCollection is being used as the source for an ItemsControl, changes must happen on the UI thread. So you'll need to do something to marshal thoses changes over to the UI thread. There are several ways to approach this. One is to define your own subclass of OC that does the marshaling automatically (see http://www.beacosta.com/Archive/2006_09_01_bcosta_archive.html). Another is to do the marshaling explicitly in your app code. The latter would work better for the initial population of the collection, where presumably you want to add lots of Contacts all at once.

Neither of these feels right, because they don't really support two independent threads. Solving that problem is quite difficult and requires some cooperation from the app. It's on our list of problems to address in v2.