Behavior is something that we have know very good in the past that we can build something into the WPF system. There is Behavior class where can use as a base calss if we want to build our own behavior entities.
From its definition, you can see that
And we will demonstrate the use of Behavior class with the following examples
we have some data model where we want to display the table with some ListView, while we don't want to hard-coded the headers information because the table's metadata can change. so we will make a ListView behavior.
so , we first define some helper classes. this is for the DependencyProperty helper classes.
using System; using System.ComponentModel; using System.Windows; using System.Windows.Data; namespace BehaviorBaseClass.Behaviors { public static class DependencyPropertyExtensions { // Use Use this method with extreme caution - it can lead to memory leaks in case if you don't call RemovePropertyListener! public static void SetPropertyListener( this DependencyProperty property, object component, EventHandler handler) { var descriptor = DependencyPropertyDescriptor.FromProperty(property, component.GetType()); if (descriptor != null) descriptor.AddValueChanged(component, handler); } public static void RemovePropertyListener( this DependencyProperty property, object component, EventHandler handler) { var descriptor = DependencyPropertyDescriptor.FromProperty(property, component.GetType()); if (descriptor != null) descriptor.RemoveValueChanged(component, handler); } public static void RefreshPropertyValueFromBinding( this DependencyProperty property, DependencyObject component) { var binding = BindingOperations.GetBindingExpressionBase(component, property); if (binding != null) binding.UpdateTarget(); } } }
and below is the ListViewBehaivour classes.
using System; using System.Collections; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Interactivity; namespace BehaviorBaseClass.Behaviors { public class ListViewBehaviour : Behavior<ListView> { public static readonly DependencyProperty DataSourceProperty = DependencyProperty.Register("DataSource", typeof (IEnumerable), typeof (ListViewBehaviour), new PropertyMetadata(OnDataSourceChanged)); private ICollectionView _dataCollectionView; public IEnumerable DataSource { get { return (IEnumerable) GetValue(DataSourceProperty); } set { SetValue(DataSourceProperty, value); } } protected ICollectionView DataCollectionView { get { return _dataCollectionView; } } protected static void OnDataSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var behavior = d as ListViewBehaviour; if (behavior == null) return; behavior.OnDataCollectionChanged(GetDefaultCollectionView(e.NewValue as IEnumerable)); } protected virtual void OnDataCollectionChanged(ICollectionView newView = null) { _dataCollectionView = newView; PopulateColumns(); } protected static ICollectionView GetDefaultCollectionView(IEnumerable enumerable) { if (enumerable == null) return null; return CollectionViewSource.GetDefaultView(enumerable); } private void PopulateColumns() { var gridView = AssociatedObject.View as GridView; var collection = _dataCollectionView as ICollectionView; if (gridView != null && collection != null) { gridView.Columns.Clear(); foreach (var col in collection) { var statusColumn = new GridViewColumn() { Header = col, DisplayMemberBinding = new Binding(col.ToString()) }; gridView.Columns.Add(statusColumn); } } } private ICollectionView GetCollectionView() { return GetDefaultCollectionView(DataSource) ?? AssociatedObject.Items; } protected override void OnAttached() { base.OnAttached(); ICollectionView view = GetCollectionView(); ItemsControl.ItemsSourceProperty.SetPropertyListener(AssociatedObject, OnAssociatedObjectItemsSourceChanged); } private void OnAssociatedObjectItemsSourceChanged(object sender, EventArgs e) { PopulateColumns(); } protected override void OnDetaching() { OnDataCollectionChanged(); } } }
As you can tell, you have to make your behavior class inherits from the Behavior<T> where the T is the Decorated classes, since we will decorate this behaviors on the ListViews, so we expand the T as the ListVIew.
and you can use it as such .
<ListView ItemsSource="{Binding RiskViewerService.RiskData}"> <ListView.View> <GridView> </GridView> </ListView.View> <i:Interaction.Behaviors> <b:ListViewBehaviour DataSource="{Binding RiskViewerService.Columns}"></b:ListViewBehaviour> </i:Interaction.Behaviors> </ListView>