WPF DataGrid calls BeginEdit on an IEditableObject two times? - wpf

I've got a DataGrid bound to a collection of IEditableObject's.
Now when I click two times in a cell, it will be opened for editing.
Funny thing is: BeginEdit will be called two times. Sometimes for the same EditableObject, but sometimes for two different objects (especially when I use PgDn until I hit the end of the DataGrid) the correct one will be called first, then some other item from the collection, which never had been in focus before.
EndEdit is called twice, too, but always for the selected Item, not for the wrong one.
Is this a known problem? Any workarounds to get only (the right) one notification.

If you look at the stack trace in the debugger when BeginEdit is called, you'll see that the first time, it's the collection view calling it, and the second time, it's a BindingGroup.
The problem appears to be that there are two things that both think they are in charge of the IEditableObject state. When WPF provides a default collection view, it will look for IEditableObject on the objects in the collection, and will call BeginEdit and either EndEdit or CancelEdit in response to calls to the corresponding IEditableCollectionView methods. But also, the BindingGroup will call the IEditableObject methods in response to calls to BeginEdit and CommitEdit or CancelEdit.
The DataGrid uses both features: when you start and complete edits in a row, it notifies the IEditableCollectionView and the BindingGroup and both of those things think that it's their responsibility in turn to go on and notify the IEditableObject implementation on the underlying source object.
So it looks rather like a bug in the DataGrid - it causes two different objects to call BeginEdit (and related methods). And it's because it makes use of editable collection views and binding groups - from the look of it, those weren't designed to be used at the same time on the same objects, in the way that the DataGrid uses them.
The reason you don't see this problem with the grid in the Toolkit is that it appears to be a slightly older version - comparing the code in that with what Reflector shows for .NET 4.0, you'll see that the .NET 4.0 DataGrid has some extra code (a new method, EnsureItemBindingGroup, and some related code in MeasureOverride and OnRowValidationRulesChanged) that ensures that a binding group always exists, whether you ask for it or not. So if the WPF Toolkit is updated, it'll probably grow a similar feature unless this gets fixed. (And I would guess that if you use the current edition - February 2010 as I write this - of the WPF Toolkit, and you use the ItemBindingGroup property to ask explicitly for a binding group, you'd see exactly the same problem.)
This doesn't explain how you'd get calls to BeginEdit on random objects as you've described. I can't repro that. But it does explain double calls on the selected object. The best thing to do appears to be to code your source objects so that they will tolerate the double calls.

I'm not sure what you'd use to interrupt the BeginEdit event before it happens, but for EndEdit a simple isDirty marker will do. In your Entity class that implements IEditableObject, add the following:
private bool _isDirty = false;
#region IEditableObject Members
public void BeginEdit()
{
// Bug Fix: Windows Controls call EndEdit twice; Once
// from IEditableCollectionView, and once from BindingGroup.
// This makes sure it only happens once after a BeginEdit.
_isDirty = true;
}
public void CancelEdit() { }
public void EndEdit()
{
if (ItemEndEdit != null && _isDirty)
{
_isDirty = false;
ItemEndEdit(this);
}
}
#endregion

I have same problem using .NET Framework 4 DataGrid.
Add Reference to last version of WPFToolkit
Add
xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
and change <DataGrid> with <dg:DataGrid>

+1 #IanGriffiths for diagonsing the Problem. As for a solution (or workaround rather), you can count the number of "pending" Edits. That means something like:
void BeginEdit()
{
_numEdits++;
}
void CancelEdit()
{
if(--_numEdits < 0)
throw new Exception("WTF?");
}
void EndEdit()
{
CancelEdit();
if(_numEdits == 0)
commitEdit();
}

Related

What is the worst gotcha in WPF?

I've started to make myself a list of "WPF gotchas": things that bug me and that I had to write down to remember because I fall for them every time....
Now, I'm pretty sure you all stumbled upon similar situations at one point, and I would like you to share your experience on the subject:
What is the gotcha that gets you all the time? the one you find the most annoying?
(I have a few issues that seem to be without explanation, maybe your submissions will explain them)
Here are a few of my "personnal" gotchas (randomly presented):
For a MouseEvent to be fired even when the click is on the "transparent" background of a control (e.g. a label) and not just on the content (the Text in this case), the control's Background has to be set to "Brushes.Transparent" and not just "null" (default value for a label)
A WPF DataGridCell's DataContext is the RowView to whom the cell belong, not the CellView
When inside a ScrollViewer, a Scrollbar is managed by the scrollviewer itself (i.e. setting properties such as ScrollBar.Value is without effect)
Key.F10 is not fired when you press "F10", instead you get Key.System and you have to go look for e.SystemKey to get the Key.F10
... and now you're on.
Always watch the output window for
binding errors. Ignoring the output
window is a recipe for tears.
Use PresentationTraceOptions.TraceLevel="High" in a binding to get verbose binding information when debugging binding failures.
Make static, unchanging resources such as brushes PresentationOptions:Freeze="True" to save resources at runtime.
Use the WPF DataGrid as a datagrid. Modifying it to behave like Excel is a massive pain in the butt.
BindingList<T> does not play well with CollectionViewSource. Expose ObservableCollection<T> from your viewmodels instead.
The internet supplies half a dozen different ideas for displaying CueBanner text in a WPF textbox. They are all broken.
1) One that used to get me every half an hour when I was making my transition from WinForms: use TextBlock instead of Label when putting random text on the UI (or don't use any tag at all, if the text is static)!
2) DataTriggers/Triggers can't be put into Control.Triggers, but have to go into Control.Styles/Style/Style.Triggers
3) Property's type must implement IList, not IList<T>, if the property is to be recognized by XAML as a collection property.
4) Bindings capture exceptions.
5) Use singleton converters/static converter class, so you don't have to create a new converter every time you use it.
6) A type for default value of DependencyProperty has to be clearly specified: 0u as uint, (float) 0 as float, 0.0 as double...
7) It matters if the control's property definitions are before or after its content.
8) NEVER use PropertyMetadata to set a default value of reference type DependencyProperty. The same object reference will be assigned to all instances of the owning class.
When first starting out, the main gotchas that would get me would be
Lists not updating due to forgetting
to use ObservableCollection
Properties not being updated either
forgetting to add OnPropertyChanged
or incorrectly typing the property
name
Recently I have stumbled across these issues
Application failing to start due to
corrupt font cache
StringFormat localization issues
If enabled, Button.IsCancel assigns false to Window.DialogResult but Button.IsDefault no.
They are so similar and for me it seemed intuitive at first that both should close dialog. I usually break MVVM and fix this in code-behind
Button.IsCancel + Command = Dialog won't close (Window.DialogResult left unassigned) but Command executes
As I understand it: If IsCancel had higher priority than Command then on Esc it would assign 'false' to DialogResult and Command won't be called. Or, if Command would have higher priority then it would be called first and DialogResult would be assigned. I don't understand how it is skipped?
Binding swallows exceptions!
It not only steals time while debugging it is also wrong from the OOP point of view because if exception is thrown it means that something exceptional had happened somewhere in our system (anything from wrong data supply to unauthorized access to memory failure) so it can be handled only if you know what to do. You can't just catch(Exception){} catch 'em all and then ignore. If there is unknown exception in program it should notify user, log and close not pretend like everything is ok...
HeaderContent can have only one child control and has no padding
Everything should have padding even logical controls (containers), right? I think it is inconsistent. What do you think?
If you set focus to ListBox via FocusManager.FocusedElement you still won't be able to switch it's content with keyboard because focus is set to ListBoxes frame not it's content. I think I don't know other UI API that would expose something like controls frame to UI programmer it should be encapsulated from us because abstractly ListBox represents a list, it is just a list of things not a list of things in a box. ok it has box in its name but still... We almost have two different controls here.
MVVM not breaking fix
ListBox.IsSynchronizedWithCurrentItem by default is false so if you assign different value or null to ItesSource then SelectedItem still holds old value until user selects something from a new list. It could mess up CanExecute for example. Need to set it every time by hand.
No binding exposed in PasswordBox results in time waste and dirty hacks... But still it has a string property PasswordBox.Password exposed so don't even try to argue about security because Snoop...
It is not a gotcha but table layout is so IE6 IMO. Container design helps separate content from its layout.
Because every time I need to change something in places I need to mess up with Grid.Row and Grid.Column. Yes, we have DockPanel, StackPanel and others but you can't do some column alignment inside of them. (And DockPanel is like completely separate gotcha) If UniformGrid would be more customizable it would be ideal I think. You always need to choose between Grid and Panels and usually if you gain something you loose something else.
I got a pretty nifty one last week:
When Templating a RichTextBox, the event handling inside the template follows a strange route that has nothing to do neither with tunnelling nor bubbling
e.g.: In the case of an event that is supposed to tunnel: the event first tunnels through the ContentPresenter, then it tunnels back from the top of the template.
see my question on the subject
ToolTips and ContextMenus not sharing the DataContext of its owner? I think that gets everyone at first
There is no clean way to handle validation in WPF, I am not a fan of magic string which IDataErrorInfo offers by default:
public string this[string columnName]
{
if (columnName == "FirstName")
{
if (string.IsNullOrEmpty(FirstName))
result = "Please enter a First Name";
}
}
However, I have tried many frameworks like SimpleMVVM, FluentValidation and MVVMValidation and BY FAR MVVM Validation is the best getting to do stuff like:
Validator.AddRule(() => RangeStart,
() => RangeEnd,
() => RuleResult.Assert(RangeEnd > RangeStart, "RangeEnd must be grater than RangeStart");
My personal favorite is this one:
public double MyVariable
{
get { return (double)GetValue(MyVariableProperty); }
set { SetValue(MyVariableProperty, value); }
}
public static readonly DependencyProperty MyVariableProperty = DependencyProperty.Register(
"MyVariable", typeof(double), typeof(MyControl), new UIPropertyMetadata(0));
Try it, once this property is declared it will crash. Why? Because 0 can't be assigned to a double using reflection apparently.
Not really a gotcha but an advice: Use Snoop or something similar, if you don't use it you must be crazy ... Crazy i tell ya!
Binding.StringFormat only works if the type of the target property is string.
TreeView's SelectedItem property is not settable. Instead you have to bind TreeViewItem's IsSelected property to your item's viewmodel and set your selection there.
ListBox's SelectedItem, on the other hand is settable, but item selection is not equal to item focus. If you want to implement proper keyboard navigation along with selecting items from within viewmodel, you have to implement manual focus fix, like:
public void FixListboxFocus()
{
if (lbFiles.SelectedItem != null)
{
lbFiles.ScrollIntoView(lbFiles.SelectedItem);
lbFiles.UpdateLayout();
var item = lbFiles.ItemContainerGenerator.ContainerFromItem(viewModel.SelectedFile);
if (item != null && item is ListBoxItem listBoxItem && !listBoxItem.IsFocused)
listBoxItem.Focus();
}
}
...and call it every time you change selected item from viewmodel:
SelectedFile = files.FirstOrDefault();
viewAccess.FixListboxFocus();

WPF MVVM application - ICollectionView/Threading/General Questions

I have a few questions regarding to building WPF MVVM applications.
1) I'm using ICollectionView objects for databound controls such as ListView and ComboBox. I found this was the simplest way of gaining access to/tracking the selected item of these controls. What is the best way to replace the contents of ICollectionView? Currently I'm doing it like so:
private ICollectionView _files;
public ICollectionView Files {
get { return _files; }
}
void _service_GetFilesCompleted(IList<SomeFile> files) {
this.IsProcessing = false;
_files = CollectionViewSource.GetDefaultView(files);
_files.CurrentChanged += new EventHandler(FileSelectionChanged);
OnPropertyChanged("Files");
}
I didn't know whether it was necessary to reattach the handler every time I refresh the list of files?
2) Now that I've got my head round it, I am starting to like the MVVM pattern. However, one concept I'm not completely sure about is how to send notifications back down to the view. Currently I am doing this by binding to properties on my ViewModel. For example, in the above code I have an "IsProcessing" property that I use to determine whether to display a ProgressBar. Is this the recommended approach?
3) Following on from 2) - there doesn't seem to be a standard way to handle exceptions in an MVVM application. One thought I had was to have one method on my ViewModel base class that handled exceptions. I could then inject an IMessagingService that was responsible for relaying any error messages. A concrete implementation of this could use MessageBox.
4) I have a few tasks that I want to perform asynchronously. Rather than adding this logic directly in my service I created a decorator service that runs the underlying service methods on a new thread. It exposes a number of events that my ViewModel can then subscribe to. I have listed the code below. I understand that BackgroundWorker is a safer option but did not know whether it was suitable for running multiple asynchronous tasks at once?:
public void BeginGetFiles()
{
ThreadStart thread = () => {
var result = _serviceClient.GetUserFiles(username, password);
GetFilesCompleted(result.Files);
};
new Thread(thread).Start();
}
Finally, I realize that there are a number of MVVM frameworks projects that handle some of these requirements. However, I want to understand how to achieve the above using built-in functionality.
Thanks
If you have ListViews and ComboBoxes, you should really be considering an ObservableCollection<> to bind to these controls. Adding and removing items from the collection will automatically notify the control the property has changed.
If you're doing background processing, you can look at the BackgroundWorker or DispatcherTimer to handle updates to the UI. These both have the capability of acting on the UI thread, and can be thread safe.
To get the selected item from a combo box, expose an INotifyCollectionChanged object such as ObservableCollection and bind it to the itemsource, then create another property for the current item and binding ComboBox.SelectedItem (or ComboBox.SelectedValue if required) to it. You will need to manage the selection when updating the collection.
On the face of it, ICollectionView seems like the obvious choice but the WPF implementation really forces your hand on some threading code that you really shouldn't be troubled with.
I used ICollectionView and CollectionViewSource recently (for filtering) and have become frustrated with how many dispatcher issues have crept in. Today I am probably going to revert to the method i describe above.

Are "volatile" data bindings in Windows Forms possible?

Let's assume I'm implementing a Winforms UI where all commands adhere to the following pattern:
interface ICommand
{
bool CanExecute { get; }
void Execute();
}
Buttons or menu items that trigger such a command should have the following set-up:
property Enabled is bound to the command's CanExecute
event Click is linked to the command's Execute (through an intermediate event handler due to the differing method signatures)
The trouble with CanExecute is, implementing INotifyPropertyChanged for it won't work here, as this property cannot be directly modified, but depends on other factors in the program which needn't be related to the command. And one shouldn't have to trigger the command's PropertyChanged event in completely unrelated parts of the program.
How do you let the data binding manager know when CanExecute has changed?
Here's a (purly fictional) example of my problem:
bool CanExecute
{
get
{
return User.LoggedInForAtLeastNMinutes(5);
// how would you trigger data-binding updates for CanExecute?
}
}
Ideally, I'd like to have the UI constantly checking CanExecute (as if it were a volatile field), but AFAIK this is not how Winforms data binding works. Does anyone have a solution for this problem?
Note: I am aware of WPF, btw. The background of my question is that I'm going to gradually improve an existing Winforms application in the general direction of WPF. But actually using WPF and thus getting rid of the problem I've asked about is not feasible right now.
I would implement INotifyPropertyChanged regardless (or add a CanExecuteChanged event, which has the same effect). I would try hard for objects to know when to raise the property changed event at the right time, rather than polling.
For instance, in your fictional example, you could have a UserLoggedIn event. In response to that, you could set a 5-minute timer; when that timer elapses, you raise the property changed event.
If you go for the polling approach then you face two dangers:
Polling too often, where your application consumes CPU checking for events that can't possibly happen yet (for instance, polling every 10 seconds to see if 5 minutes are up)
Not polling often enough, where controls bound to CanExecute properties lag the rest of the UI (for instance, a delay between making a text selection and the CopyTextCommand.CanExecute property updating)
A hybrid approach is that taken by Microsoft Foundation Classes in C++, which was to make this check any time the application's message loop was idle. This is a reasonable approach when you know that only user interface interaction that can affect your CanExecute property.
Use a Timer to constantly poll the CanExecute property. Raise the PropertyChanged event when the property changes.
I' do the polling on the Application.Idle event, as long as your can execute logic is simple, there shouldn't be any problem.
here is an extract of my current 'CommandManager' implementation;
public CommandManager()
{
Commands = new List<ICommand>();
Binders = new List<ICommandBinder>
{
new ControlBinder(),
new MenuItemCommandBinder()
};
Application.Idle += UpdateCommandState;
}
private void UpdateCommandState(object sender, EventArgs e)
{
Commands.Do(c => c.Enabled);
}
(Do() is just an extension method that does a foreach, like linq Select() but taking Action instead of Func)
I've blogged about this some time ago, feel free to check: http://codewithpassion.blogspot.com/2010/11/icommand-and-commandmanager-for-windows.html
hope it helps

Increasing WPF ObservableCollection performance

At present I have two WPF listboxes imitating the following functionality
(source: psu.edu)
I am using 2 ObservableCollections to allow users to select whatever items they require (flexibility is the key here). The main issue is that I have thousands of items that are grouped in both listboxes. All in all the design works really well (with a few dozen items), but my stumbling block is when a user copies all the available items from the left to the right as the screen freezes (time to run on a different thread?).
Looking at ObservableCollection it lacks an AddRange method and there are various implementations available on the internet. I also know the CollectionChanged event is needlessly being fired as each item is copied over draining performance horribly.
It may well be that I have to allow users to choose from groups of over 10 000 items in the future, which sounds like a bad idea, but is non-negotiable as the grouping on the listbox (CollectionViewSource) works really well, but has the side effect of switching off the Virtualising of both the listboxes
What can I do to improve the performance when loading a listbox with thousands of items when databound to an ObservableCollection? Are there any AddRange type implementations that you would recommend? Is the only choice I have here to run this on a background thread which seems expensive because I am not loading data from a database?
I have removed the CollectionViewSource and the grouping and the items are copied over in 1/2 a second, but with the grouping on it can take up to a minute because virtualisation does not work with the grouping.
I will need to decide whether to use the CollectionViewSource
I couldn't resist answering this. I don't think you won't need this answer anymore, but maybe somebody else can use it.
Don't think too hard (do not approach this multithreaded (this will make things error-prone and unnecessary complicated. Only use threading for hard calculations/IO), all those different actiontypes will make it very difficult to buffer. The most annoying part is, that if you remove or add 10000 items your application (listboxes) will be very busy with handling the events raised by the ObservableCollection. The event already supports multiple items. So.....
You could buffer the items until it changes the action. So Add actions will be buffered and wil be raised as batch if the 'user' changes action or flushes it.
Haven't test it, but you could do something like this:
// Written by JvanLangen
public class BufferedObservableCollection<T> : ObservableCollection<T>
{
// the last action used
public NotifyCollectionChangedAction? _lastAction = null;
// the items to be buffered
public List<T> _itemBuffer = new List<T>();
// constructor registeres on the CollectionChanged
public BufferedObservableCollection()
{
base.CollectionChanged += new NotifyCollectionChangedEventHandler(ObservableCollectionUpdate_CollectionChanged);
}
// When the collection changes, buffer the actions until the 'user' changes action or flushes it.
// This will batch add and remove actions.
private void ObservableCollectionUpdate_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// if we have a lastaction, check if it is changed and should be flush else only change the lastaction
if (_lastAction.HasValue)
{
if (_lastAction != e.Action)
{
Flush();
_lastAction = e.Action;
}
}
else
_lastAction = e.Action;
_itemBuffer.AddRange(e.NewItems.Cast<T>());
}
// Raise the new event.
protected void RaiseCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (this.CollectionChanged != null)
CollectionChanged(sender, e);
}
// Don't forget to flush the list when your ready with your action or else the last actions will not be 'raised'
public void Flush()
{
if (_lastAction.HasValue && (_itemBuffer.Count > 0))
{
RaiseCollectionChanged(this, new NotifyCollectionChangedEventArgs(_lastAction.Value, _itemBuffer));
_itemBuffer.Clear();
_lastAction = null;
}
}
// new event
public override event NotifyCollectionChangedEventHandler CollectionChanged;
}
Have fun!, J3R03N
You could probably inherit from ObservableCollection<T> (or directly implement INotifyCollectionChanged) to add BeginUpdate and EndUpdate methods. Changes made between calls to BeginUpdate and EndUpdate would be queued, then combined into one (or several if there are separate ranges) NotifyCollectionChangedEventArgs object that would be passed to the handlers of the CollectionChanged event when EndUpdate is called.
You can find a Thread safe observable collection here. Make your Observable collection thread safe and bind it to listbox.

WPF: how to signal an event from ViewModel to View without code in codebehind? [duplicate]

This question already has answers here:
How can I Have a WPF EventTrigger on a View trigger when the underlying Viewmodel dictates it should?
(4 answers)
Closed 8 years ago.
I have quite simple (I hope :)) problem:
In MVVM, View usually listens on changes of ViewModel's properties. However, I would sometimes like to listen on event, so that, for example, View could start animation, or close window, when VM signals.
Doing it via bool property with NotifyPropertyChanged (and starting animation only when it changes from false to true) is possible, but it feels like a hack, I'd much prefer to expose event, as it is semantically correct.
Also, I'd like to do it without code in codebehind, as doing viewModel.myEvent += handler there would mean that I'd have manually unregister the event in order to allow View to be GC'd - WPF Views are already able to listen on properties 'weakly', and I'd much prefer to program only declaratively in View.
The standard strong event subscription is also bad, because I need to switch multiple ViewModels for one View (because creating View every time takes too much CPU time).
Thank you for ideas (if there is a standard solution, a link to msdn will suffice)!
Some comments:
You can use the weak event pattern to ensure that the view can be GC'd even if it is still attached to the view model's event
If you're already switching multiple VMs in for the one view, wouldn't that be the ideal place to attach/detach the handler?
Depending on your exact scenario, you could just have the VM expose a state property which the view uses as a trigger for animations, transitions, and other visual changes. Visual state manager is great for this kind of thing.
This is something that I wrestled with as well...
Similar to what others are saying, but here is an example with some code snippets... This example shows how to use pub/sub to have a View subscribe to an event fired by the VM - in this case I do a GridView. Rebind to ensure the gv is in sync with the VM...
View (Sub):
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Events;
private SubscriptionToken getRequiresRebindToken = null;
private void SubscribeToRequiresRebindEvents()
{
this.getRequiresRebindToken =
EventBus.Current.GetEvent<RequiresRebindEvent>()
.Subscribe(this.OnRequiresRebindEventReceived,
ThreadOption.PublisherThread, false,
MemoryLeakHelper.DummyPredicate);
}
public void OnRequiresRebindEventReceived(RequiresRebindEventPayload payload)
{
if (payload != null)
{
if (payload.RequiresRebind)
{
using (this.gridView.DeferRefresh())
{
this.gridView.Rebind();
}
}
}
}
private void UnsubscribeFromRequiresRebindEvents()
{
if (this.getRequiresRebindToken != null)
{
EventBus.Current.GetEvent<RequiresRebindEvent>()
.Unsubscribe(this.getRequiresRebindToken);
this.getRequiresRebindToken = null;
}
}
Call unsub from the close method to prevent memory leaks.
ViewModel (Pub):
private void PublishRequiresRebindEvent()
{
var payload = new RequiresRebindEventPayload();
payload.SetRequiresRebind();
EventBus.Current.GetEvent<RequiresRebindEvent>().Publish(payload);
}
Payload class
using System;
using Microsoft.Practices.Composite.Presentation.Events;
public class RequiresRebindEvent
: CompositePresentationEvent<RequiresRebindEventPayload>
{
}
public class RequiresRebindEventPayload
{
public RequiresRebindEventPayload()
{
this.RequiresRebind = false;
}
public bool RequiresRebind { get; private set; }
public void SetRequiresRebind()
{
this.RequiresRebind = true;
}
}
Note that you can also set the constructor up to pass in a Guid, or some identified in, which can be set on Pub and checked on sub to be sure pub/sub is in sync.
imho yYand separated
state - to be able to move data back/forth between view <-> vm
actions - to be able to call onto view model functions/commands
notifications - to be able to signal to the view that something has happened and you want it to take a viewy action like make an element glow, switch styles, change layout, focus another element etc.
while is true that you can do this with a property binding, its more of a hack as tomas mentioned; always has felt like this to me.
my solution to be able to listen for 'events' from a view model aka notifications is to simple listen for data-context changes and when it does change i verify the type is the vm i'm looking for and connect the events. crude but simple.
what i would really like is a simple way to define some 'view model event' triggers and then provide some kind of handler for it that would react on the view side of things all in the xaml and only drop to code behind for stuff thats not do-able in xaml
Like adrianm said, when you trigger your animation off a bool property you are actually responding to an event. Specifically the event PropertyChanged which the WPF subsystem. Which is designed to attach/detach correctly to/from so that you don't leak memory (you may forget to do this when wiring an event yourself and cause a memory leak by having a reference active to an object which otherwise should be GCed).
This allows you to expose your ViewModel as the DataContext for the control and respond correctly to the changing of properties on the datacontext through databinding.
MVVM is a pattern that works particularly well with WPF because of all these things that WPF gives you, and triggering off a property change is actually an elegant way to use the entire WPF subsystem to accomplish your goals :)
A more general question to ask is: "Why am I trying to deal with this event in my ViewModel?"
If the answer has anything to do with view-only things like animations, I'd argue the ViewModel needs not know about it: code behind (when appropriate), Data/Event/PropertyTriggers, and the newer VisualStateManager constructs will serve you much better, and maintain the clean separation between View and ViewModel.
If something needs to "happen" as a result of the event, then what you really want to use is a Command pattern - either by using the CommandManger, handling the event in code behind and invoking the command on the view model, or by using attached behaviors in the System.Interactivity libs.
Either way, you want to keep your ViewModel as "pure" as you can - if you see anything View-specific in there, you're probably doing it wrong. :)

Resources