Refactoring to attached behavior
At the project I’m currently working on, I had to integrate Telerik’s RadScheduleView in a WPF application that uses Caliburn Micro as MVVM framework. The RadScheduleView is a time management component, however, we needed it only for presentation – thus we had to make it a read only control.
The control itself does not expose an “IsReadOnly” property, so I found this post at Telerik’s forums. It includes a code sample that shows how to do it, but it does not conform nicely to the M-V-VM Pattern – So I had to refactor it to Attached Behavior.
The Problem: Code in Code-Behind
The demo project places the event handling code of 4 events (AppointmentCreating, AppointmentDeleting, AppointmentEditing and ShowDialog) in the code behind the MainWindow (MainWindow.xaml.cs file).
Since we’re using Caliburn, we did not want to break pattern and add code to our view’s .xaml.cs file. This way, our code behind will remain slim and clean.
The Solution: Attached Behaviors
Attached Behaviors enable changing of behavior of WPF controls in a declarative manner, with no unwanted code residue in the view.
The magic uses Attached Properties: Since attached properties are dependency properties, code can register to a property change event. The event handler then modifies the control’s properties and events to have the required functionality.
(Code is provided as-is.)
public static class ReadOnlyBehavior
private const string INVALID_TYPE_ERROR_MESSAGE =
"This attached behavior can only be aplied on RadScheduleView controls." ;
public static bool GetIsReadOnly(DependencyObject obj)
return (bool )obj.GetValue(IsReadOnlyProperty);
public static void SetIsReadOnly(DependencyObject obj, bool value)
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty .RegisterAttached("IsReadOnly" ,
typeof (bool ),
typeof (ReadOnlyBehavior ),
new UIPropertyMetadata (false ,
private static void IsReadOnlyChanged(DependencyObject d,
if (d == null )
throw new ArgumentNullException ("d" );
var scheduleView = d as RadScheduleView ;
if (scheduleView == null )
throw new ArgumentException (INVALID_TYPE_ERROR_MESSAGE, "d" );
var shouldBeReadOnly = (bool )e.NewValue;
var shouldCleanup = (bool )e.OldValue;
private static void UnregisterInteractionEventHandlers(RadScheduleView scheduleView)
scheduleView.AppointmentCreating -= CancelAppointmentCreating;
scheduleView.AppointmentDeleting -= CancelAppointmentDeleting;
scheduleView.AppointmentEditing -= CancelAppointmentEditing;
private static void RegisterInteractionEventHandlers(RadScheduleView scheduleView)
scheduleView.AppointmentCreating += CancelAppointmentCreating;
scheduleView.AppointmentDeleting += CancelAppointmentDeleting;
scheduleView.AppointmentEditing += CancelAppointmentEditing;
private static void CancelAppointmentEditing(object sender,
e.Cancel = true ;
private static void CancelAppointmentDeleting(object sender,
e.Cancel = true ;
private static void CancelAppointmentCreating(object sender,
e.Cancel = true ;
Now, this behavior can be applied in XAML like this:
<!– … –>
In order for the project to compile, I have to change the ReadOnlyDragAndDropBehavior’s base class inherit from ScheduleViewDragDropBehavior and not from DefaultDragDropBehavior, as it is obsolete.
Next Possible Steps
It is also possible to turn this Attached Behavior to a System.Windows.Interactivity.Behavior, but we thought it would be overshooting.
Another option to include the ReadOnlyDragAndDropBehavior in the attached behavior, but since I knew we’re not going to set the behavior to re-enable editing, and the assignment is still done in xaml, I did not really care about where to set it.
ReUpdate: It turnes out that the RadScheduleView is the new control of the two.. If you need to migrate, Telerik has a help post about it.
Enjoy, and happy coding!