Page 3 of 5
Now we can move on to consider how to let the user set some of the cells to a live state. The simplest thing to do is to allow them to click on a cell and change its state.
To do this we need to add a MouseLeftButtonDown event handler to the Grid. Move back to the Designer and select the inner grid. Move to the Properties Window and select the Event tab. Now scroll down to the MouseLeftButtonDown event and double click on it. A MouseLeftButtonDown event handler will be created for you and you will be transferred to the editor to start working on it. Its default name is grid1_MouseLeftButtonDown_1.
Notice that for reasons that are not entirely clear Silverlight doesn't have a simple MouseDown event but splits this action into two MouseLeftButtonDown and MouseRightButtonDown events.
At this point you might be thinking that we have to spend a lot of time working out from the mouse position which Ellipse had been clicked on - well you don't have to because of the way routed events work.
The MouseLeftButtonDown event is actually raised on the Ellipse that the user clicked on and, because the Ellipse doesn't handle it, it bubbles up to the Grid which does handle it. The point is that the OriginalSource property of the event Args contains a reference to the object that was clicked on, i.e the Ellipse in question, so we don't have to work out which Ellipse is involved as we are told this as part of the event.
We have to check that the source of the event is indeed an Ellipse but apart from this we can simply cast to Ellipse and update. The only problem is that we don't want to update the Ellipse - we want to update the cell in the array that corresponds to the Ellipse and let databinding update the Ellipse automatically. All we have to do to find out which cell in the array is bound to the Ellipse is examine its DataContext and cast to a cell:
private void grid1_MouseLeftButtonDown_1(
object sender, MouseButtonEventArgs e)
if (e.OriginalSource is Ellipse)
Cell C = (Cell)temp.DataContext;
C.state = !C.state;
An alternative would have been to implement a two-way data binding and simply update the Ellipses Opacity property but sometimes a direct approach is easier.
At this point you can now run the program and attempt to draw on the Grid - but nothing happens. The problem is that while the initial setting of the cell's state was transferred to the Ellipses when everything was being set up, there is nothing to trigger the Ellipse's property update when the cell's state changes.
So although you are changing the cell's state when you click on an Ellipse, this isn't being transferred to the Ellipse's bound property.
The solution is very simple - you have to implement the INotifyPropertyChanged interface.
You first need make sure that there is a:
at the start of the program and add to the Cell class:
class Cell: INotifyPropertyChanged
To implement the interface you have to define an event:
public event PropertyChangedEventHandler
which has to be raised when the property is changed. To do this we need to modify the set modifier functions:
_state = value;
if (PropertyChanged != null)
The if statement checks to see whether another object has subscribed to the event. If it has it raises the event with parameters set to the object that the property belongs to and the name of the property that has changed. Notice that once added to a class the same event can be used to signal a change on any property.
Now if you run the program you can click on an Ellipse (or where an Ellipse is hidden) and it will change its state.
A starting pattern