In the previous posts in this series (Attaching Behaviors from the Expression Blend SDK using Styles and Attaching Behaviors from the Expression Blend SDK using Styles (Part 2)), I introduced the reader to a new attached property that gives the ability to attach a collection of behaviors to an item through a style.
I received feedback from two developers regarding a bug in the code that was in Part 2, and as a result I wanted to post a corrected version of the code.
Rather than do a walk through, here is the full, revised version of the StylizedBehaviors class:
using System.Windows;
using System.Windows.Interactivity;
#endregion
namespace LivingAgile.Common.Presentation.WPF.Behaviors
{
public class StylizedBehaviors
{
#region Fields (private)
private static readonly DependencyProperty OriginalBehaviorProperty =
DependencyProperty.RegisterAttached(
@"OriginalBehaviorInternal", typeof (Behavior), typeof (StylizedBehaviors), new UIPropertyMetadata(null));
#endregion
#region Fields (public)
public static readonly DependencyProperty BehaviorsProperty = DependencyProperty.RegisterAttached(
@"Behaviors",
typeof (StylizedBehaviorCollection),
typeof (StylizedBehaviors),
new FrameworkPropertyMetadata(null, OnPropertyChanged));
#endregion
#region Static Methods (public)
public static StylizedBehaviorCollection GetBehaviors(DependencyObject uie)
{
return (StylizedBehaviorCollection) uie.GetValue(BehaviorsProperty);
}
public static void SetBehaviors(DependencyObject uie, StylizedBehaviorCollection value)
{
uie.SetValue(BehaviorsProperty, value);
}
#endregion
#region Static Methods (private)
private static Behavior GetOriginalBehavior(DependencyObject obj)
{
return obj.GetValue(OriginalBehaviorProperty) as Behavior;
}
private static int GetIndexOf(BehaviorCollection itemBehaviors, Behavior behavior)
{
int index = -1;
Behavior orignalBehavior = GetOriginalBehavior(behavior);
for (int i = 0; i < itemBehaviors.Count; i++)
{
Behavior currentBehavior = itemBehaviors[i];
if (currentBehavior == behavior
|| currentBehavior == orignalBehavior)
{
index = i;
break;
}
Behavior currentOrignalBehavior = GetOriginalBehavior(currentBehavior);
if (currentOrignalBehavior == behavior
|| currentOrignalBehavior == orignalBehavior)
{
index = i;
break;
}
}
return index;
}
private static void OnPropertyChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs e)
{
var uie = dpo as UIElement;
if (uie == null)
{
return;
}
BehaviorCollection itemBehaviors = Interaction.GetBehaviors(uie);
var newBehaviors = e.NewValue as StylizedBehaviorCollection;
var oldBehaviors = e.OldValue as StylizedBehaviorCollection;
if (newBehaviors == oldBehaviors)
{
return;
}
if (oldBehaviors != null)
{
foreach (var behavior in oldBehaviors)
{
int index = GetIndexOf(itemBehaviors, behavior);
if (index >= 0)
{
itemBehaviors.RemoveAt(index);
}
}
}
if (newBehaviors != null)
{
foreach (var behavior in newBehaviors)
{
int index = GetIndexOf(itemBehaviors, behavior);
if (index < 0)
{
var clone = (Behavior) behavior.Clone();
SetOriginalBehavior(clone, behavior);
itemBehaviors.Add(clone);
}
}
}
}
private static void SetOriginalBehavior(DependencyObject obj, Behavior value)
{
obj.SetValue(OriginalBehaviorProperty, value);
}
#endregion
}
}
The interested reader can refer to the comments on the previous posts to see what motivated the changes.