I know someone else smarter than me has probably written a post, an article or a book on this, but I’m going to put it up here anyways.
Tonight I was screwing around with some code for a small side project (also known as experimentation in a real world domain) and I figured that I needed to have a couple of classes fire events every time that any of their properties changed. I’ve done this kind of thing before in my glorious VB6 past, but I hadn’t had the need nor opportunity in C#. I figured I would take the time to document it here so that I wouldn’t forget it and, as you’ll see in a second, so that I could download the files easily.
The Pattern1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32public delegate void ChangingHandler(object sender, PropertyChangingArgs args);
public delegate void ChangedHandler(object sender, PropertyChangedArgs args);
public event ChangingHandler NameChanging;
public event ChangedHandler NameChanged;
private string _name;
public string Name
{
get
{
return _name;
}
set
{
PropertyChangingArgs changingArgs = new PropertyChangingArgs(Name, value);
if (NameChanging != null)
{
NameChanging(this, changingArgs);
}
if (changingArgs.Cancel == false)
{
_name = value;
PropertyChangedArgs changedArgs = changingArgs;
if (NameChanged != null)
{
NameChanged(this, changedArgs);
}
}
}
}
Supporting Classes1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64public class PropertyChangedArgs : EventArgs
{
public PropertyChangedArgs()
{
}
public PropertyChangedArgs(object beforeValue, object afterValue)
{
this.BeforeValue = beforeValue;
this.AfterValue = afterValue;
}
private object _beforeValue = new object();
public object BeforeValue
{
get
{
return _beforeValue;
}
set
{
_beforeValue = value;
}
}
private object _afterValue = new object();
public object AfterValue
{
get
{
return _afterValue;
}
set
{
_afterValue = value;
}
}
}
public class PropertyChangingArgs : PropertyChangedArgs
{
public PropertyChangingArgs()
{
}
public PropertyChangingArgs(object beforeValue, object afterValue)
: base(beforeValue, afterValue)
{
}
private bool _cancel = false;
public bool Cancel
{
get
{
return _cancel;
}
set
{
_cancel = value;
}
}
}
The Implementation1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public void LoadPage()
{
Equipment equip = new Equipment();
equip.NameChanged += new ChangedHandler(NameChanged);
equip.NameChanging += new ChangingHandler(NameChanging);
}
private void NameChanged(object sender, PropertyChangedArgs args)
{
int i = 1;
}
private void NameChanging(object sender, PropertyChangingArgs args)
{
int i = 1;
}
In the end I created a block of code and supporting classes that has a pre-change (Changing) and post change (Changed) event for a property. The pre-change event has a parameter of PropertyChangingArgs with a Cancel property. Setting that property equal to true will cancel the update of the property value. Nice to do if you set your validation to be executed in the pre-change event and the validation fails.
Once I got the code written for the first property on the class I was working with, I proceeded to start manually writing the code for each of the other properties (about 25 in all). I quickly realized that this was both boring and error prone so I decided to delve into Visual Studio 2005’s Code Snippet functionality to speed the process. You can find my code snippets, complete with the two supporting ‘Args’ classes here (download). All you have to do to add the two snippets to the IDE is copy the two files to the following folder
My Documents\Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets
Because the delegates only need to appear once per class, I have created those as a separate code snippet. Once you’ve copied the files the two code snippets will appear in intellisense as prope (creates the property with the event code) and propedelg which creates the two delegate lines that appear at the top of the Pattern section of this post. To use the code that the snippets generate you will need to include the two ‘Args’ classes either in the same project that the code is being generated in or in a project that is referenced.