472,985 Members | 2,703 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,985 software developers and data experts.

Binding to INotifyCollectionChanged event

I am trying to bind a WPF dependency property to an aggregate of a
collection. I've implemented a wrapper around a Dictionary that
implements INotifyCollectionChanged to fire the event when items are
added or removed.

Debugging through it I notice that there is nothing listening to the
event after I bind to it which I expected the SetBinding to do as I
don't know what delegate to attach to the event. It's the binding that
needs updating after all.

I've tried a test with just an ObservableCollection to see if I was
missing something but that doesn't work either.

How do I wire up the event to the binding or do whatever it takes to
get my test to pass?

Here's my test code:

[TestClass()]
public class ObservableDictionaryTest : DependencyObject
{
public class MaxDoubleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object
parameter, System.Globalization.CultureInfo culture)
{
if (value is IEnumerable<double>)
{
return ((IEnumerable<double>)value).Max(); // using
Linq
}

throw new ArgumentException("Cannot covert " +
value.GetType() + " to IEnumerable<double>", "value");
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

public double Max
{
get { return (double)GetValue(MaxProperty); }
}

public static readonly DependencyProperty MaxProperty =
DependencyProperty.Register("Max", typeof(double),
typeof(ObservableDictionaryTest), new PropertyMetadata(0.0));

[TestMethod()]
public void TestBindingToObservableCollection()
{
ObservableCollection<doublevalues = new
ObservableCollection<double>();
values.Add(1.0);
values.Add(2.0);
values.Add(3.0);

Binding b = new Binding();
b.Converter = new MaxDoubleConverter();
b.Source = values;
b.Mode = BindingMode.OneWay;
BindingOperations.SetBinding(this, MaxProperty, b);

Assert.AreEqual(3.0, Max); // this works

values.Add(4.0);
Assert.AreEqual(4.0, Max); // this doesn't

values.Remove(4.0);
Assert.AreEqual(3.0, Max);
}
}
Jun 27 '08 #1
7 7947
What about using ObservableCollection<T>?

--
Pete
=========================================
I use Enterprise Core Objects (Domain driven design)
http://www.capableobjects.com/
=========================================
Jun 27 '08 #2
On 9 Jun, 16:22, "Peter Morris" <mrpmorris at gmail dot comwrote:
What about using ObservableCollection<T>?

--
Pete
=========================================
I use Enterprise Core Objects (Domain driven design)http://www.capableobjects.com/
=========================================
That's what the test I've posted does or do you mean use it in another
way? It's only my test class that is called ObservableDictionaryTest
(maybe I should have renamed it if that caused confusion).

I'd expect the Binding.Source setter to check if the source is
IEnumerable and if it implements INotifyCollectionChanged then listen
to the event and update the bound value when it fires.

I'm obviously not understanding how binding to an ObservableCollection
works.

Jun 27 '08 #3
>I am trying to bind a WPF dependency property to an aggregate of a
collection. I've implemented a wrapper around a Dictionary that
implements INotifyCollectionChanged to fire the event when items are
added or removed.

Debugging through it I notice that there is nothing listening to the
event after I bind to it which I expected the SetBinding to do as I
don't know what delegate to attach to the event. It's the binding that
needs updating after all.

I've tried a test with just an ObservableCollection to see if I was
missing something but that doesn't work either.

How do I wire up the event to the binding or do whatever it takes to
get my test to pass?
I think the problem is that only bindings which expect to bind to a
collection (like ListBox.ItemsSource) check for and subscribe to
INotifyCollectionChanged (though I don't know exactly how they do it).

What you could do is make your collection a property of your class, bind to
the property, implement INotifyPropertyChanged, then subscribe to the
collection's INotifyCollectionChanged yourself and raise a PropertyChanged
event. This seems rather clumsy and I'm sure there ought to be a better
way - maybe someone more knowledgeable will point it out.

Chris Jobson
Jun 27 '08 #4
On 9 Jun, 17:54, "Chris Jobson" <chris.job...@btinternet.comwrote:
I am trying to bind a WPF dependency property to an aggregate of a
collection. I've implemented a wrapper around a Dictionary that
implements INotifyCollectionChanged to fire the event when items are
added or removed.
Debugging through it I notice that there is nothing listening to the
event after I bind to it which I expected the SetBinding to do as I
don't know what delegate to attach to the event. It's the binding that
needs updating after all.
I've tried a test with just an ObservableCollection to see if I was
missing something but that doesn't work either.
How do I wire up the event to the binding or do whatever it takes to
get my test to pass?

I think the problem is that only bindings which expect to bind *to a
collection (like ListBox.ItemsSource) check for and subscribe to
INotifyCollectionChanged (though I don't know exactly how they do it).

What you could do is make your collection a property of your class, bind to
the property, implement INotifyPropertyChanged, then subscribe to the
collection's INotifyCollectionChanged yourself and raise a PropertyChanged
event. This seems rather clumsy and I'm sure there ought to be a better
way - maybe someone more knowledgeable will point it out.

Chris Jobson
Thanks.

One other idea I had was that it was the DependencyProperty that
needed refreshing so I tried subscribing to the event and calling
InvalidateProperty(MaxProperty), but that didn't work either, it still
came out as 3.0 somehow and the Convert was never called again so the
3.0 isn't being invalidated.

I'll try your idea since the collection will be a property of a
UserControl once I get it working.
Jun 27 '08 #5
>I am trying to bind a WPF dependency property to an aggregate of a
collection. I've implemented a wrapper around a Dictionary that
implements INotifyCollectionChanged to fire the event when items are
added or removed.

Debugging through it I notice that there is nothing listening to the
event after I bind to it which I expected the SetBinding to do as I
don't know what delegate to attach to the event. It's the binding that
needs updating after all.

I've tried a test with just an ObservableCollection to see if I was
missing something but that doesn't work either.

How do I wire up the event to the binding or do whatever it takes to
get my test to pass?
I think the problem is that only bindings which expect to bind to a
collection (like ListBox.ItemsSource) check for and subscribe to
INotifyCollectionChanged (though I don't know exactly how they do it).

What you could do is make your collection a property of your class, bind to
the property, implement INotifyPropertyChanged, then subscribe to the
collection's INotifyCollectionChanged yourself and raise a PropertyChanged
event. This seems rather clumsy and I'm sure there ought to be a better
way - maybe someone more knowledgeable will point it out.

Chris Jobson
Jun 27 '08 #6
After looking into this a bit more I found
http://www.drwpf.com/Blog/Default.as...=36&EntryID=18 that told
me that it is a CollectionView that does the subscribing to
CollectionChanged in ListBox and the like.

Naturally I tried wrapping my collection in a CollectionView and
setting that as the source but now the Max property doesn't get
evaluated at all (my converter is never called) so thebinding is
treating the view differently to any other plain IEnumerable, like it
thinks it doesn't need to do anything if it already has a
CollectionView.

This seems like one of those times when I'm digging deeper than I need
to and all this clever Binding and CollectionView stuff does what I
need if only I knew how to use it properly.
Jun 27 '08 #7
After looking into this a bit more I found
http://www.drwpf.com/Blog/Default.as...=36&EntryID=18 that told
me that it is a CollectionView that does the subscribing to
CollectionChanged in ListBox and the like.
Thanks for that link. I'd read it some time ago but had forgotten the bit
about CollectionView.
Naturally I tried wrapping my collection in a CollectionView and
setting that as the source but now the Max property doesn't get
evaluated at all (my converter is never called) so thebinding is
treating the view differently to any other plain IEnumerable, like it
thinks it doesn't need to do anything if it already has a
CollectionView.
I *think* (but could well be wrong - I find it all a bit confusing!) it's
still the same problem - binding Max to a CollectionView is more or less the
same as binding it to an ObservableCollection, and in both cases a change to
the collection won't re-evaluate Max because it isn't interested in
INotifyCollectionChanged. AIUI the special feature of CollectionView is that
it if your property is of type CollectionView then you can bind a collection
to it and the property will re-evaluate when the collection changes.

(By the way, I'm surprised your idea of InvalidateProperty(MaxProperty)
didn't work. I've never used InvalidateProperty myself, but from the
description in MSDN it sounds ideal.)

I've just come across what might be another solution to your problem -
BindableLINQ (http://www.codeplex.com/bindablelinq/). In particular this
post (http://www.paulstovell.com/blog/bind...ble-aggregates)
seems to describe something very similar to your requirement. It's only a
beta, and I've no experience of it myself, but it might be worth
investigating.

Chris
Jun 27 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Rodrigo Benenson | last post by:
Hi, I have a weird need in tkinter. If I have a widget I can *set* a binding ..bind("<the event>", the_callback) I also can *append* a binding ..bind("<the event>", the_second_callback,...
1
by: Marcin Floryan | last post by:
Hello! My question regards opening (and re-opening) Form and the Load event. I have a main form (frmMain) and I also have a data form (frmData). In the main form I have created: Private...
1
by: Jonathan Yong | last post by:
I observe a very weird behavior when dynamically create web control and bind events to it. Create a C# ASP.NET application, Put a PlaceHolder and Textbox onto the Web form, and try with the 4...
11
by: Rourke Eleven | last post by:
I have looked and searched. What good is the databind property on Radiobuttons? How does one go about actually using it? What is a good resource on this? I understand that I can easily get/set...
19
by: Simon Verona | last post by:
I'm not sure if I'm going down the correct route... I have a class which exposes a number of properties of an object (in this case the object represents a customer). Can I then use this...
0
by: Larry Serflaten | last post by:
I am not sure how many are aware of this sort of data binding, but as it is new to many (classic) VB developers I thought I would post this once just to let people know of its availablility. ...
13
by: Michael.Suarez | last post by:
Let's suppose I have an instance of MyClass, which has the properties MyText1 and MyText2, and sets the values of MyText1 and MyText2 to 'A' and 'B' in it's constructor. Let's also suppose I...
6
by: Mikus Sleiners | last post by:
Is there any way to enable exception throws in VS 2005, that occur during binding operations? I am upset that i can't see exceptions that are thrown during binding operations. It's very hard to...
6
by: Dmitry Duginov | last post by:
Hi, I have the following label markup (label is inside FormView): <asp:Label ID="lblIndicatorReady" runat="server" Text="RE" ToolTip="Ready" BackColor='<%#...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.