INotifyPropertyChanged and PropertyChangedEventHandler support
by matooo on Dec.25, 2008, under gtk-databind
Ok, so I hacked a little and complete Adaptor support for INotifyPropertyChanged and PropertyChangedEventHandler is finished. In fact, not only the way MS did it.
This solution first checks if object being connected is INotifyPropertyChanged. If it is then it connects its own delegate method which calls Notificator.ObjectChangedNotification(object). But if it is not, then it rechecks all events specified in that class for PropertyChangedEventHandler type and adds same delegate to those. This enables for much more flexibility in class planing.
If luck is on my side and I succeed to connect same to ObserveableList then support will land in svn the same minute I check the results.
Data class source (Note: for the nature how SDB works, Name is just as alive as other two properties)
using System;
using System.ComponentModel;
namespace msevent_sample1
{
///
/// Sample specifying INotifyPropertyChanged
///
public class SampleData : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string firstname = "";
///
/// Property defined as usual property according to MS.DataBinding
///
public string FirstName {
get { return (firstname); }
set {
if (firstname == value)
return;
firstname = value;
if (PropertyChanged != null)
PropertyChanged (this, new PropertyChangedEventArgs(”FirstName”));
}
}
private string lastname = "";
///
/// Property defined as usual property according to MS.DataBinding
///
public string LastName {
get { return (lastname); }
set {
if (lastname == value)
return;
lastname = value;
if (PropertyChanged != null)
PropertyChanged (this, new PropertyChangedEventArgs(”LastName”));
}
}
///
/// This is read only property, but it will act alive same as others
///
public string Name {
get { return (FirstName + ” ” + LastName); }
}
public SampleData()
{
}
public SampleData (string fname, string lname)
{
FirstName = fname;
LastName = lname;
}
}
}
And code for assignation testing (stripped out the scwl code)
SampleData data = new SampleData ("John", "Smith");
Adaptor a = new Adaptor();
Adaptor b = new Adaptor();
a.Target = data;
b.Target = data;
b.Target = null;
a.Target = null;
And since screenshot is impossible for this test, here is console output which takes care of connection and disconnection (and the fact that only single one is activated)
OUTPUT ![]()
Starting connection
==========================================
Connecting 1st adaptor
*** Connecting MS.Events
Connected INotifyPropertyChanged
==========================================
Connecting 2nd adaptor
*** Connecting MS.Events
Denied connection MS.Events (already connected)
==========================================
Disconnecting 2nd adaptor
*** Disconnecting MS.Events
Denied disconnection MS.Events (connection is still needed)
==========================================
Disconnecting 1st adaptor
*** Disconnecting MS.Events
Disconnected INotifyPropertyChanged
On the other hand
I also implemented BaseNotifyPropertyChanged class for a simple convenience. It has already specified PropertyChanged event and added method
OnPropertyChanged (string PropertyName)
I used PropertyName so everything can be compatible with standard DataBinding
Summary
Strangely, as much as I spit over some things MS did wrong. Implementing this actually presented as really good thing. SDB was already very carefully designed on memory and needs, but I have to admit that this will improve speed even more. Now instead of notifying SDB internals about every change, only changes when delegate connection is active will go through, otherwise it simply returns on if (PropertyChanged != null). Meaning notification queue will have much less to process.
Well, why not? Life can sometimes play nice with something like this free gift of gaining improvement elsewhere by doing something completely different
Adaptors (part 1 - Basics)
by matooo on Dec.20, 2008, under gtk-databind
Well, for the start first thing that should be explained is the difference and commonality between Adaptor and DataSource terms. Like first DataSource is commonly used property which specifies object that will provide data. And Adaptor? Adaptor is a class which specifies object that will provide data. wtf? That is the same? Well, yes and no. Like first one is property and one is a class.
Remember old fashioned pointers pointer can point to pointer, which can point to another pointer which points to data. A simple linked list. But we could always access end of the chain. Like every pointer list, Adaptor list can have multiple start points all converging at the same finish Target. But, in the need to be explanatory, I need to explain basic Adaptor innards.
For end user only two properties are needed to know how to use. Target and FinalTarget. And as it was already explained with pointer chain…
When resolving FinalTarget, Target simply checks if Target is IAdaptor. If it is it simply does return ((Target as IAdaptor).FinalTarget), otherwise it simply returns its own Target. Which means FinalTarget CAN NOT be IAdaptor.
Now, the harder to understand part. Widgets actually don’t care what type its DataSource is (Just to brag a little, even list widgets like DataTreeView don’t care about that. It has optimized property transfer for default type, but if type processed is of another type, it will simply use what it can and avoid what it has, but more on this latter when explaining DataTreeView). Don’t even care is Property with mapped name is. By default Gtk part of System.Data.Bindings simply disables that widget if (DataSource == null) or property with mapped name doesn’t exists in object mapped as DataSource.
As widgets DataSource you can specify any object including Adaptor and as you’ll see later, probably even preferably if you specify Adaptor as DataSource, as it offers something static data sources can’t. Flexibility and by flexibility, I really mean FLEXIBILITY.
Adaptor posts changes trough event messages to all interested parties which also includes all chain connected Adaptors. Messages as in normal language are “Hey, data changed” and “Hey, my target changed”. Which simply means that all Adaptors in chain will resolve their FinalTarget asap after TargetChanged message has been dispatched.
Last thing important to know about adaptor is DoGetFinalTarget(). By overriding this method you can specify another FinalTarget based on parameters. Just as in case of MappedAdaptor. MappedAdaptor resolves its data target differently. Instead of providing FinalTarget like usual Adaptor, MappedAdaptor resolves the usual way and then after that resolves mapped property. Here is a nice example of such data classes:
class Person {
....
}
class Company {
....
Person Manager { .... }
}
Which is following the mapping code:
Adaptor a = new Adaptor();
MappedAdaptor ma = new MappedAdaptor();
ma.Mappings = "Manager";
ma.Target = a;
So, what do we have here now? Lets say we have company1 and company2 objects pointing at two different data.
By simply pointing
a.Target = company1;
all widgets connected to either a or ma adaptors will reflect change and display/edit new data. As easy as that. Practically same as “xxx.xxx” type of property mapping, except that it is all part of one same engine, which means it works the same as everything else Adaptor based.
There is one another big difference between MS data bindings and SDB+GDB. All widgets can have InheritedDataSource, which simply means it will inherit DataSource from first container specifying its own DataSource, but if that container specifies InheritedDataSource = true; then it will inherit it from its parent container and so on.
By using Adaptor, MappedAdaptor, InheritedDataSource and Mapping correctly, you can simply map gui into one big living thing. Specify data source once and all gui will reflect it. Never connect or disconnect. All that connection/disconnection is happening automatically.
Which concludes Adaptor (part 1 - Basics)
Another short “why not”
by matooo on Dec.19, 2008, under gtk-databind
One of the questions that were raised once too often is why I didn’t support complex mapping to subproperty something like “Manager.Name”. Well, I did… But not like that, no matter how much I wished to make this work like this, it never was 100%. Either memory lacked, was not flexible enough, didn’t work as it should. So I decided on another bulletproof solution called MappedAdaptor. For now, the only important thing is the fact that it works, but explanation will follow today or tomorrow when I’ll tackle with the explanation what Adaptor is, how to use it, how it works and how to make specialized adaptor subclasses.
Big Databinding misconception
by matooo on Dec.19, 2008, under gtk-databind
Making real Databound classes instead of half assed
The more I look at people that use it, the more I see how wrong their view on Databinding is. Majority of fault for this probably goes to companies like Borland and Microsoft. They simply did as always do. Make a great solution, but don’t take it to the state where it is finished.
Now… why wrong? First and foremost problem of typical software in its source is data is being used and controlled in the form source instead of its own source. This is simply plain stupidity. The only thing you get is that two or more source files depend on every change you make to data and its access. Instead of creating data self aware they create data and plug its awareness into form… wtf? Now, if they would be dentists instead of coders, they would be pulling teeth trough customers ass.
In real solution… you don’t want your forms know the data, they just have to reflect it and edit it. Because, if they do, it means you did something wrong. In that case of software change you don’t edit only class and form separately, you also need to check all connections, and the more times you were involved in the data process, the more points you have to maintain. But if you avoid that, then maintaining software will be a real peace of cake.
System.Data.Bindings and Gtk.DataBindings already take a lot of measures to ease the development. One example is making your software use more than one thread. In usual approach you have to be carefull where you touch gui interface. Set one value from wrong thread and your gui freezes. All data has to be assigned by using Gtk.Invoke(delegate{}). So, if you’d connect simple change event of some class to assign value of widget? You better assign that object trough Gtk.Invoke too or your data to widget assigning delegate has to do that. By using SDB and GDB? All is taken cared off. Simply forget you’re writing multi threaded application. It just works.
Validators and Converters? Another WTF?
So,… here we are at second thing I never understood in MS DataBindings. Validators and Converters? If you travel by car and want to have bike ready for “just in case”, you don’t park bikes on every 100m of your travel route, you rather pack one in trunk. Same goes with Validators and Converters.
private int month;
public int Month {
get { return (month); }
set {
if ((value < 1) || (value > 12))
throw new Exception (”Validation at work”);
// Try to check current property value, so you don’t assign
// same one
// if more than one part of your class is depending on it
// Databinding triggers message queue about its change
// so if you’re assigning same value, you’ll just create
// non sense round tripping
if (month == value)
return;
// Assign value
month = value;
// And now contact your message queue
Notificator.ObjectChangedNotification (this);
// *** version 2.0 of System.Data.Bindings will also
// *** support MS events for property changes
// *** in form of
// if (monthChanged != null)
// monthChanged…
}
}
As we see, validation code is (and belongs) in set part of property. As much as I tried I coudn’t figure out one single example that would demand external validation.
And Converters? For gods sake, use the same tactics. Instead of faking middle ground to do what you need it to do. Rather make good and solid ground where it belongs…. on the ground.
Make converter in your object code
public string MonthName {
get { /* do your code to get month name from Month */ }
set { /* do your code to assign Month property based on months */ }
}
Now bound this property to where you think you’d otherwise need Converter from int to string for month.
Another common misconception why people need Converters.
Yeah, but my data is complex and I would like to access part of it in my control.
if you think like this, you’re not thinking from the side you should be thinking it. In real world example, if your car stays out of gas, you won’t add drops directly into engine, you’ll fill the gas tank.
And same example in System.Data.Bindings? What you’re interested in is not middle point converting data, you’re interested in control that will eat and spit your data. If data is simple all you need is to override GetDataFromDataSource and PutDataToDataSource for most suitable widget to fulfil your need and here is your perfect conversion. Now if data is complex? Monodevelop has everything you need… a perfect widget creation. It creates Gtk.Box as ground. Put Table onto it, put new widgets on that control and make it data bound (beside the writing insides of GetDataFromDataSource and PutDataToDataSource, procedure is one single copy/paste). Or in simpler case, put DataTable into that Box, insert data aware widgets into that table (don’t forget to set InheritedDataSource = true on them) and set correct Mappings for each Widget.
Difference? Now you have reusable specialized widgets and self validated classes. And again… code source for data separated from code source for form.
Or in my case… I simply added code template (specifying the code for making widget data aware) into MonoDevelop as gtkdataaware. Now I simply say, New Widget, write gtkdataaware, press TAB and edit GetDataFromDataSource and PutDataToDataSource as needed. 5 minute job.
And last rant for today
One part of the problem is understandable when looking at MS DataBindings. They use notifications that say “Hey, this property changed”, so control can update it self as needed. My first SDB incarnation used the same solution just to be deleted. The string comparisons took way too much CPU, just to make it less usable. I swapped notifications to report only “Hey, this object changed”. And what is the difference? If you have:
// Read only property
public string BoldName {
get { return ("<b>" + Name + "</b>"); }
}
then this property never gets updated unless you handle change notification from your Name property. By avoiding the PropertyName non sense, this one changed too. So,… with less CPU, you get much more effect? Beside the fact that writing real self aware classes becomes much simpler.
ActionController usage to control actions in your application (stopwatch sample)
by matooo on Dec.18, 2008, under gtk-databind
ActionController is a class that controls different states of action widgets like ToolbarButton or Menu. It supports controlling Visibility or Sensitivity (Warning: Gtk#-2.4 has a bug which freezes interface on setting ToolbarButton invisible trough Controller, haven’t tested all but bug is not present in 2.10). Every Action can not only have specified
cntActive = new ActionController (selection, "", "",
new ActionMonitor (ActionMonitorType.Sensitivity, removeAction,
new ActionMonitorDefaults (ActionMonitorDefaultsType.NotNullTarget)),
new ActionMonitor (ActionMonitorType.Visibility, propertiesAction,
new ActionMonitorDefaults (ActionMonitorDefaultsType.NotNullTarget))
);
this simple use is binding 2 actions, but not specified mapping to any property as it used NotNullTarget, which automatically uses Action controllers DataSource to resolve Sensitivity and Visibility to simple equation. If (DataSource == null) then result is false, otherwise result is true.
Selection is actualy defined as simple
private GtkAdaptor selection = new GtkAdaptor()
and is connected to
selection.Target = Timers.CurrentSelection
Timers is simple DataTreeView and selection is GtkAdaptor??? So what does this do?
It actually triggers change on every selection change in TreeView and assigns it as target for our ActionController. Now, everything works automatically. Whenever item is selected or deselected in treeview ActionController will change state of actions. More on this in next blog post which will cover Adaptor types.
What else it is possible? You could make 1 or 2 properties and link them to ActionController. Something like
class OurStates {
private bool isVisible = false;
public bool IsVisible {
get { return (isVisible); }
set {
if (isVisible == value)
return;
isVisible = value;
Notificator.ObjectChangedNotification (this);
}
}
private bool isSensitive = false;
public bool IsSensitive {
get { return (isSensitive); }
set {
if (isSensitive == value)
return;
isSensitive = value;
Notificator.ObjectChangedNotification (this);
}
}
}
And creating action controller like this
OurStates ourStates = new OurStates();
cntActive = new ActionController (ourStates, "IsVisible", "IsSensitive",
and we can now control states simply by specifying
ourStates.IsVisible = true;
and the result? All actions connected to this datasource will make their state reflect the change. As simple as that.
Now a bit of warning. You can specify more than one ControlAdaptor to the same action, but its state will reflect the last change, so you should probably avoid this as it will become unpredictable.
And another thing which is very informative in this case…
public enum ActionMonitorType
{
/// Monitores visibility
Visibility,
/// Monitores sensitivity
Sensitivity,
/// Monitores visibility with inverted value
InvertedVisibility,
/// Monitores sensitivity with inverted value
InvertedSensitivity
}
public enum ActionMonitorDefaultsType
{
/// true when DataSource Target is not null
NotNullTarget,
/// Will be possible to be true only if DataSource is valid (is null)
NeedsValid,
/// Will be possible to be true even if DataSource is not valid (is null)
Always
}
This is how you can really refine choice about when action is visible and sensitive.
Well, that would be all in this little tip.
Memory and reference handling in System.Data.Bindings
by matooo on Dec.17, 2008, under gtk-databind
Well, for one important thing I noticed from various sources is incorrect handling of references. Most of the people used simply:
SomeWidget.DataSource = new ArrayList();
Ok, that should work in MS databinding, but not in System.Data.Bindings. SDB is way too carefully designed to post one single reference on that object. Which means GC will collect it asap. Until I was using real and not weak references, memory usage went sky high and GC was anything but effective, after that change, SDB became lean, mean and very resource friendly engine. I practically cut memory usage to less than 30%.
Which takes it to how you should use it.
// make var to keep reference alive
ArrayList somelist = new ArrayList();
somewidget.DataSource = somelist;
... CODE
// and now datasource will be kept alive until somelist is alive
somelist = null;
GC should probably be effective in both cases the same, but unfortunatelly it is not. Second (how you should do it) will free list from memory much sooner. I don’t know if this is a bug or feature in Mono. But as long as first example stays memory hungry, I won’t change it to be workable.
Solution to first example while keeping me happy would be if I could count references per object in GC during DataSource assign and keep my reference manager. Haven’t really looked into this as I don’t find it as pressing bug. But to be honest *This is planned 2.0 feature*.
On my life note
Moving into new appartment, coding my non-free project which is used as testing base for SDB and GDB and Metal Gear Online consumed me way too much time to be able to work on SDB and GDB until now, just sqashing bugs as they showed.
Ok, time for new development on my lib
by matooo on Dec.16, 2008, under gtk-databind
Stress testing of old version
Latest pre 1.0 version has finally received stress tests that made me think it is time to roll 1.0, or 1.9.01. I was writing pretty large project that works with master-client data relationship, has on fly downloads in background and works on heavily cached mechanism. Software is just entering final 1.0 stage and then I’ll be getting feedback from at least 200 users. And since complete UI is based on gtk-databind project, it also means library will finally receive real world testing.
Skipping 1.0? WTF?
Why skipping 1.0? Well, the version I used (and resides in svn) has quite a few features more than 1.0 should. I also implemented DataBinder which enables one to simply do:
DataBinder.Bind (Obj1, "PropName", Obj2, "PropName");
And the two are bound together. By default it implements Simple (one way). Implementing TwoWay communication is as simple as specifying EBindDirection.TwoWay into same Bind call.
DataBinder.Bind (EBindDirection.TwoWay, Obj1, "PropName", Obj2, "PropName");
Off course, using this is only alive when properties call
Notificator.ObjectChangedNotification (this);
in their set { … } method. Which forces me to do my ramblings part of this blog on the first post already.
MS.Evented DataSource using “PropertyName”+”Changed”
As far as I looked into MS implementation (and that is not much) they heavily depend on every property having its PropertyName+”Changed” event. Binding or adding that one is very simple, but as every simple thing always has, there is a major showstopper. Not every library is conforming to that late to the table statement. And to make things even worse, parameters differ from event to event.
Currently all properties need to be declared with
private int aval = -1;
public int AVal {
get { return (aval); }
set {
aval = value;
Notificator.ObjectChangedNotification (this);
}
}
Gtk# for example.
Basic Gtk.Widget:
- Visibilty does not invoke VisibilityChanged but rather VisibilityNotifyEvent
- Sensitivity does not invoke any event
Basic Gtk.Entry widget:
- Text does not invoke TextChanged but rather Changed
Solution
Making few classes into System.Data.Bindings EventCompatibilityAttribute, EventCompatibilityDescription and loader which loads whole compatibility information from all referenced libraries.
At that moment binding to event from MappedProperty becomes really easy as engine would know how to interact with properties.
Result
Databinding would be able to work with simplified object/property declarations, which now simply is not possible. One has to call Notificator by him self.
And now the real rambling part
All this event/property roundtripping and all of the clumsy Reflection crap could be avoided if Framework design would have simple thing inside its specs.
PropertyInfo which could get/set SetMethod and SetMethod to be returning bool value (if value changed). This would be usefull for extending functionality to existing libraries and for debugging purposes. Even if it is per System.Type not per object (off course, specifying it per object would rock really hard).
Specifying PropertyName+”Changed” is all well and nice. But what if developers don’t follow that spec. The last thing one would want is modifying every library he is using just to maintain it for his purposes.
Wrapup
Ok, to finish this. This blog will now be regularly maintained and I’ll be either posting tips on how to use this library or updates on development.