/************************************************************************************* Extended WPF Toolkit Copyright (C) 2007-2013 Xceed Software Inc. This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license For more features, controls, and fast professional support, pick up the Plus Edition at http://xceed.com/wpf_toolkit Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids ***********************************************************************************/ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Collections; using System.Windows.Data; namespace Xceed.Wpf.Toolkit.Core.Utilities { /// /// This helper class will raise events when a specific /// path value on one or many items changes. /// internal class ValueChangeHelper : DependencyObject { #region Value Property /// /// This private property serves as the target of a binding that monitors the value of the binding /// of each item in the source. /// private static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( object ), typeof( ValueChangeHelper ), new UIPropertyMetadata( null, OnValueChanged ) ); private object Value { get { return ( object )GetValue( ValueProperty ); } set { SetValue( ValueProperty, value ); } } private static void OnValueChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args ) { ( ( ValueChangeHelper )sender ).RaiseValueChanged(); } #endregion public event EventHandler ValueChanged; #region Constructor public ValueChangeHelper(Action changeCallback) { if( changeCallback == null ) throw new ArgumentNullException( "changeCallback" ); this.ValueChanged += ( s, args ) => changeCallback(); } #endregion #region Methods public void UpdateValueSource( object sourceItem, string path ) { BindingBase binding = null; if( sourceItem != null && path != null ) { binding = new Binding( path ) { Source = sourceItem }; } this.UpdateBinding( binding ); } public void UpdateValueSource( IEnumerable sourceItems, string path ) { BindingBase binding = null; if( sourceItems != null && path != null ) { MultiBinding multiBinding = new MultiBinding(); multiBinding.Converter = new BlankMultiValueConverter(); foreach( var item in sourceItems ) { multiBinding.Bindings.Add( new Binding( path ) { Source = item } ); } binding = multiBinding; } this.UpdateBinding( binding ); } private void UpdateBinding( BindingBase binding ) { if( binding != null ) { BindingOperations.SetBinding( this, ValueChangeHelper.ValueProperty, binding ); } else { this.ClearBinding(); } } private void ClearBinding() { BindingOperations.ClearBinding( this, ValueChangeHelper.ValueProperty ); } private void RaiseValueChanged() { if( this.ValueChanged != null ) { this.ValueChanged( this, EventArgs.Empty ); } } #endregion #region BlankMultiValueConverter private class private class BlankMultiValueConverter : IMultiValueConverter { public object Convert( object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture ) { // We will not use the result anyway. We just want the change notification to kick in. // Return a new object to have a different value. return new object(); } public object[] ConvertBack( object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture ) { throw new InvalidOperationException(); } } #endregion } }