silverlight 3 collection binding
Someone please help me understand why this binding does not work...
I have a class called SelectionManager with a property called 'dates' which is populated by a WCF service. The property is an array of structs which bundles a DateTime and an integer count of business objects.
public class SelectionManager : INotifyPropertyChanged {
... other properties ...
public DQMServiceDateCountPair[] dates { get; private set; }
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName) {
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); }
}
I have another class called DateSelector which has a DependencyProperty called 'pairs' setup to be the binding target of 'dates'.
public partial class DateSelector : UserControl {
... other stuff ...
public static readonly DependencyProperty pairsProperty = DependencyProperty.Register(
"pairs",
typeof(DQMServiceDateCountPair[]),
typeof(DateSelector),
new PropertyMetadata(new DQMServiceDateCountPair[0])
);
public DQMServiceDateCountPair[] pairs {
get { return (DQMServiceDateCountPair[])GetValue(pairsProperty); }
set {
Debug.WriteLine("adding dates");
SetValue(pairsProperty, value);
dateMode = DateMode.Years;
}
}
}
In my MainPage.xaml, I have a line like this:
<date:DateSelector x:Name="dateSelector" pairs="{Binding dates}" />
It's weird, because all my other bindings in MainPage.xaml update correctly, including a ComboBox bound to 'dates'. My UserControl however, will not update. The Debug.Writeline doesn't get called in the set statement of the 'pairs' property.
In playing around with it, I've tried making the DQMServiceDateCountPair[] property into an ObservableCollection and implementing INotifyCollectionChanged, but that doesn't help.
If I leave either the source property or the target property as an array, and make the other an Obse开发者_如何转开发rvableCollection, then I get a binding error that says it can't automatically convert one to the other, so Silverlight seems aware of the binding, it just doesn't update it.
Can anyone help?
P.S. I'm using Silverlight 3.
Try changing your code as follows:
1. Add DataMember/DataContract attributes
2. Make "set" public
[DataContract]
public class SelectionManager : INotifyPropertyChanged {
[DataMember]
public DQMServiceDateCountPair[] dates { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName) {
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); }
}
Whats actually wierd is that the other stuff is working when you've coded your class the way you have. My guess is that the dates
array gets set by some code that runs internally in your selection manager on completion of a WCF request.
Howerver whilst you have implemented INotifyPropertyChanged you aren't actually raising the event that it defines. You can't really combine INotifyPropertyChanged with the Auto-property C# syntax. You need this:-
public SelectionManager : INotifyPropertyChanged
{
private DQMServiceDateCountPair[] myDates;
public DQMServiceDateCountPair[] dates
{
get { return myDates; }
set
{
myDates = value;
NotifyPropertyChanged("dates");
}
// rest of your code
}
So, here's what what going on. The binding has been working perfectly well this whole time. For the past week I've been struggling with this, it's been happily updating along--but because of a faulty assumption on my part, I could never see it.
In case anyone else harbors this faulty assumption, let me spell it out:
The GetValue and SetValue calls are not made automatically by virtue of the fact that you are declaring a Dependency Property. The "new PropertyMetadata()" part of the declaration has an overload that takes a callback method. In this callback method, you have to set the property value yourself. For instance, in my code, I made this the PropertyMetadata call:
new PropertyMetadata(new PropertyChangedCallback(OnPairsPropertyChanged))
and the callback method reads like this:
private static void OnPairsPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) {
((DateSelector)d).pairs = (DQMServiceDateCountPair[])e.NewValue;
}
Thanks to everyone who tried to help!
精彩评论