Reputation: 6147
I've written a custom control and I have two collection dependency properties SourceA and SourceB. You'll see in the code below that the dependency properties 'PropertyChanged' methods are exactly the same, it seems like a lot of redundant code.
SourceB_PropertyChanged...
SourceA_PropertyChanged...
I don't feel like I'm doing this properly. Is there a way for me to remove the redundancy while maintaining the Notification for collection changed?
The Code
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace NexusEditor
{
/// <summary>
/// The main class that implements the network/flow-chart control.
/// </summary>
public partial class NexusEditor : Control
{
#region Dependency Property/Event Definitions
private static readonly DependencyPropertyKey ItemsPropertyKey =
DependencyProperty.RegisterReadOnly("Items", typeof(ObservableCollection<object>), typeof(NexusEditor),
new FrameworkPropertyMetadata());
public static readonly DependencyProperty ItemsProperty = ItemsPropertyKey.DependencyProperty;
public static readonly DependencyProperty SourceAProperty =
DependencyProperty.Register("SourceA", typeof(IEnumerable), typeof(NexusEditor),
new FrameworkPropertyMetadata(SourceA_PropertyChanged));
public static readonly DependencyProperty SourceBProperty =
DependencyProperty.Register("SourceB", typeof(IEnumerable), typeof(NexusEditor),
new FrameworkPropertyMetadata(SourceB_PropertyChanged));
#endregion
#region Constructors
public NexusEditor()
{
// Create a collection to contain nodes.
this.Items = new ObservableCollection<object>();
}
static NexusEditor()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NexusEditor), new FrameworkPropertyMetadata(typeof(NexusEditor)));
}
#endregion
#region properties
public IEnumerable SourceA
{
get { return (IEnumerable)GetValue(SourceAProperty); }
set { SetValue(SourceAProperty, value); }
}
public IEnumerable SourceB
{
get { return (IEnumerable)GetValue(SourceBProperty); }
set { SetValue(SourceBProperty, value); }
}
/// <summary>
/// Collection of items
/// </summary>
public ObservableCollection<object> Items
{
get { return (ObservableCollection<object>)GetValue(ItemsProperty); }
private set { SetValue(ItemsPropertyKey, value); }
}
#endregion
#region privates
private static void UpdateItems(NexusEditor editor)
{
editor.Items.Clear();
var sourceB = editor.SourceB as IEnumerable;
if (sourceB != null)
{
foreach (object obj in sourceB)
{
editor.Items.Add(obj);
}
}
var sourceA = editor.SourceA as IEnumerable;
if (sourceA != null)
{
foreach (object obj in sourceA)
{
editor.Items.Add(obj);
}
}
}
/// <summary>
/// Event raised when a new collection has been assigned to the SourceB property.
/// </summary>
private static void SourceB_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
NexusEditor c = (NexusEditor)d;
if (e.OldValue != null)
{
var notifyCollectionChanged = e.OldValue as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged -= new NotifyCollectionChangedEventHandler(c.SourceB_CollectionChanged);
}
}
if (e.NewValue != null)
{
var notifyCollectionChanged = e.NewValue as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged += new NotifyCollectionChangedEventHandler(c.SourceB_CollectionChanged);
}
}
UpdateItems(c);
}
/// <summary>
/// Event raised when a node has been added to or removed from the collection assigned to 'NodesSource'.
/// </summary>
private void SourceB_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateItems(this);
}
/// <summary>
/// Event raised when a new collection has been assigned to the SourceB property.
/// </summary>
private static void SourceA_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
NexusEditor c = (NexusEditor)d;
if (e.OldValue != null)
{
var notifyCollectionChanged = e.OldValue as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged -= new NotifyCollectionChangedEventHandler(c.SourceA_CollectionChanged);
}
}
if (e.NewValue != null)
{
var notifyCollectionChanged = e.NewValue as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged += new NotifyCollectionChangedEventHandler(c.SourceA_CollectionChanged);
}
}
UpdateItems(c);
}
/// <summary>
/// Event raised when a node has been added to or removed from the collection assigned to 'NodesSource'.
/// </summary>
private void SourceA_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateItems(this);
}
#endregion
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
}
}
Upvotes: 0
Views: 163
Reputation: 8843
Why don't you create one PropertyChanged
handler method named Source_PropertyChanged
for example and use that for both dependency properties?
If they're exactly the same you can just do that.
public static readonly DependencyProperty SourceAProperty =
DependencyProperty.Register("SourceA", typeof(IEnumerable), typeof(NexusEditor),
new FrameworkPropertyMetadata(Source_PropertyChanged));
public static readonly DependencyProperty SourceBProperty =
DependencyProperty.Register("SourceB", typeof(IEnumerable), typeof(NexusEditor),
new FrameworkPropertyMetadata(Source_PropertyChanged));
The handler:
private static void Source_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
NexusEditor c = (NexusEditor)d;
if (e.OldValue != null)
{
var notifyCollectionChanged = e.OldValue as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged -= new NotifyCollectionChangedEventHandler(c.Source_CollectionChanged);
}
}
if (e.NewValue != null)
{
var notifyCollectionChanged = e.NewValue as INotifyCollectionChanged;
if (notifyCollectionChanged != null)
{
notifyCollectionChanged.CollectionChanged += new NotifyCollectionChangedEventHandler(c.Source_CollectionChanged);
}
}
UpdateItems(c);
}
For the collection changed:
private void Source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateItems(this);
}
Upvotes: 1