Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
530
xamDataChart adding scatterplot dynamically with MVVM
posted

I am using xamdataChart  with multiple datachart, scatterline/scattercontour etc.  I would like to dynamically add series to the chart via MVVM.

I saw a solution for this but it is quite old, from 8 years ago. I modified it a little to accept ScatterContours but I am having a problem onValueMemberPath.

I nee to have 3 datachart,two off them add scatter line, and the last one add scatter contour.

Can someone notify the problem, or simple provide my a more recent solution to the problem?

Thank you!

ps: I couln'tupload my zip so hre is my code

Main window.xaml

<Window xmlns:ig="http://schemas.infragistics.com/xaml"  x:Class="SeriesBinder.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SeriesBinder"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="50" />
        </Grid.RowDefinitions>
        <ig:XamDataChart Margin="2" >
            <local:SeriesBinderBehavior.SeriesBinder>
                <local:SeriesBinderInfo
                    SeriesSource="{Binding SeriesSource}"
                    ItemsSourcePath="Source"
                    XMemberPath="XPath"
                    YMemberPath="YPath"
                        
                    TypePath="Type"/>
                    
            </local:SeriesBinderBehavior.SeriesBinder>
        </ig:XamDataChart>


        <ig:XamDataChart Grid.Row="1" >
            <local:SeriesBinderBehavior.SeriesBinder>
                <local:SeriesBinderInfo
                    SeriesSource="{Binding SeriesSource2}"
                    ItemsSourcePath="Source"
                    XMemberPath="XPath"
                    YMemberPath="YPath"
                    TypePath="Type"/>
                <!--  ValuMemberPathmissing -->

            </local:SeriesBinderBehavior.SeriesBinder>
        </ig:XamDataChart>


        <Button Content="Add Series" Command="{Binding AddSeries}" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="12,15,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
        <Button Content="Remove Series" Command="{Binding RemoveSeries}" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="93,15,0,0" Name="button2" VerticalAlignment="Top" Width="94" />
        <Button Content="Clear Series" Command="{Binding ClearSeries}" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="193,15,0,0" Name="button3" VerticalAlignment="Top" Width="75" />
        <Button Content="Reset Source" Command="{Binding ResetSeries}" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="274,15,0,0" Name="button4" VerticalAlignment="Top" Width="75" />
    </Grid>
</Window>

Main window.cs

using Infragistics.Controls.Charts;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

namespace SeriesBinder
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel();
        }
    }

    #region Series Binder

    public class SeriesBinderBehavior : DependencyObject
    {
        public static readonly DependencyProperty SeriesBinderProperty =
            DependencyProperty.RegisterAttached(
                "SeriesBinder",
                typeof(SeriesBinderInfo),
                typeof(SeriesBinderBehavior),
                new PropertyMetadata(null,
                    (o, e) =>
                    {
                        OnSeriesBiderChaged(o as XamDataChart,
                            e.OldValue as SeriesBinderInfo,
                            e.NewValue as SeriesBinderInfo);
                    }));

        public static SeriesBinderInfo GetSeriesBinder(DependencyObject target)
        {
            return target.GetValue(SeriesBinderProperty) as SeriesBinderInfo;
        }

        public static void SetSeriesBinder(DependencyObject target, object value)
        {
            target.SetValue(SeriesBinderProperty, value);
        }


        private static void OnSeriesBiderChaged(
            XamDataChart chart,
            SeriesBinderInfo oldVal,
            SeriesBinderInfo newVal)
        {
            if (chart == null)
            {
                return;
            }
            if (oldVal != null)
            {
                oldVal.DetachOwner(chart);
            }
            if (newVal != null)
            {
                newVal.AttachOwner(chart);
            }
        }
    }

    public class SeriesBinderInfo : FrameworkElement
    {
        #region Fields
        private XamDataChart _owner;
        Dictionary<object, Series> _seriesObjectMapper;
        #endregion

        #region Constructor

        public SeriesBinderInfo()
        {
            _seriesObjectMapper = new Dictionary<object, Series>();
        }

        #endregion

        #region Initializing Methods

        public void AttachOwner(XamDataChart chart)
        {
            if (_owner != null)
            {
                DetachOwner(_owner);
            }
            _owner = chart;
            SetBinding(DataContextProperty,
                new Binding("DataContext")
                {
                    Source = _owner
                });

        }

        public void DetachOwner(XamDataChart _owner)
        {
            _owner = null;
            _seriesObjectMapper.Clear();
            ClearValue(DataContextProperty);
        }

        #endregion  

        #region Properties

        #region SeriesSource

        private const string SeriesSourcePropertyName = "SeriesSource";

        public IEnumerable SeriesSource
        {
            get { return (IEnumerable)GetValue(SeriesSourceProperty); }
            set { SetValue(SeriesSourceProperty, value); }
        }

        public static readonly DependencyProperty SeriesSourceProperty =
            DependencyProperty.Register(
                SeriesSourcePropertyName,
                typeof(IEnumerable),
                typeof(SeriesBinderInfo),
                new PropertyMetadata(null));

        #endregion

        #region ItemsSourcePath

        private const string ItemsSourcePathPropertyName = "ItemsSourcePath";

        public string ItemsSourcePath
        {
            get { return (string)GetValue(ItemsSourcePathProperty); }
            set { SetValue(ItemsSourcePathProperty, value); }
        }

        public static readonly DependencyProperty ItemsSourcePathProperty =
            DependencyProperty.Register(
                ItemsSourcePathPropertyName,
                typeof(string),
                typeof(SeriesBinderInfo),
                new PropertyMetadata(null));


        #endregion

        #region XMemberPath

        private const string XMemberPathPropertyName = "XMemberPath";

        public string XMemberPath
        {
            get { return (string)GetValue(XMemberPathProperty); }
            set { SetValue(XMemberPathProperty, value); }
        }

        public static readonly DependencyProperty XMemberPathProperty =
            DependencyProperty.Register(
                    XMemberPathPropertyName,
                    typeof(string),
                    typeof(SeriesBinderInfo),
                    new PropertyMetadata(null));

        #endregion

        #region YMemberPath

        private const string YMemberPathPropertyName = "YMemberPath";

        public string YMemberPath
        {
            get { return (string)GetValue(YMemberPathProperty); }
            set { SetValue(YMemberPathProperty, value); }
        }

        public static readonly DependencyProperty YMemberPathProperty =
            DependencyProperty.Register(
                    YMemberPathPropertyName,
                    typeof(string),
                    typeof(SeriesBinderInfo),
                    new PropertyMetadata(null));

        #endregion

        #region valueMemberPath

        private const string ValueMemberPathPropertyName = "ValueMemberPath";

        public string ValueMemberPath
        {
            get { return (string)GetValue(ValueMemberPathProperty); }
            set { SetValue(ValueMemberPathProperty, value); }
        }

        public static readonly DependencyProperty ValueMemberPathProperty =
            DependencyProperty.Register(
                    ValueMemberPathPropertyName,
                    typeof(string),
                    typeof(SeriesBinderInfo),
                    new PropertyMetadata(null));

        #endregion

        #region TypePath

        private const string TypePathPropertyName = "TypePath";

        public string TypePath
        {
            get { return (string)GetValue(TypePathProperty); }
            set { SetValue(TypePathProperty, value); }
        }

        public static readonly DependencyProperty TypePathProperty =
            DependencyProperty.Register(
                TypePathPropertyName,
                typeof(string),
                typeof(SeriesBinderInfo),
                new PropertyMetadata(null));



        #endregion

        #endregion

        #region Event Handlers

        void SeriesBinderInfo_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    {
                        object seriesSource = e.NewItems[0];
                        AddSeries(seriesSource);
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    {
                        object seriesSource = e.OldItems[0];
                        RemoveSeries(seriesSource);
                    }
                    break;
                case NotifyCollectionChangedAction.Move:
                case NotifyCollectionChangedAction.Replace:
                case NotifyCollectionChangedAction.Reset:
                    {
                        GenerateSeries();
                    }
                    break;
                default:
                    break;
            }
        }

        #endregion

        #region Helper Methods

        private void RemoveSeries(object seriesSource)
        {
            Series s = _seriesObjectMapper[seriesSource];
            SeriesType type = (SeriesType)seriesSource.GetType().GetProperty(TypePath).GetValue(seriesSource, null);

            UpdateSeriesProperties(s, type, seriesSource, true, true);
            _owner.Series.Remove(s);
            _seriesObjectMapper.Remove(seriesSource);
        }

        private void AddSeries(object seriesSource)
        {
            SeriesType type = (SeriesType)seriesSource.GetType().GetProperty(TypePath).GetValue(seriesSource, null);

            Series series = CreateSeries(type, seriesSource);
            _owner.Series.Add(series);

            _seriesObjectMapper.Add(seriesSource, series);
        }

        private void GenerateSeries()
        {
            _owner.Series.Clear();
            _owner.Axes.Clear();
            foreach (var item in SeriesSource)
            {
                AddSeries(item);
            }
        }

        private Series CreateSeries(SeriesType type, object seriesSource)
        {
            Series series = null;
            switch (type)
            {
                case SeriesType.LineSeries:
                    {
                        series = new LineSeries();
                        UpdateSeriesProperties(series, type, seriesSource, true, false);
                    }
                    break;
                case SeriesType.ColumnSeries:
                    {
                        series = new ColumnSeries();
                        UpdateSeriesProperties(series, type, seriesSource, true, false);
                    }
                    break;
                case SeriesType.ScatterSeries:
                    {
                        series = new ScatterSeries();
                        UpdateSeriesProperties(series, type, seriesSource, true, false);
                    }
                    break;
                case SeriesType.ScatterLineSeries:
                    {
                        series = new ScatterLineSeries();
                        UpdateSeriesProperties(series, type, seriesSource, true, false);
                    }
                    break;
                case SeriesType.ScatterContourSeries:
                    {
                        series = new ScatterContourSeries();
                        UpdateSeriesProperties(series, type, seriesSource, true, false);

                    }

                    break;
                default:
                    break;
            }

            return series;
        }

        private void UpdateSeriesProperties(Series series, SeriesType type, object seriesSource, bool shouldRenewAxes, bool clearOnly)
        {
            if (series != null)
            {
                switch (type)
                {
                    case SeriesType.LineSeries:
                    case SeriesType.ColumnSeries:
                        {
                            HorizontalAnchoredCategorySeries category = series as HorizontalAnchoredCategorySeries;
                            category.ClearValue(HorizontalAnchoredCategorySeries.ValueMemberPathProperty);
                            category.ClearValue(HorizontalAnchoredCategorySeries.ItemsSourceProperty);

                            if (!clearOnly)
                            {
                                category.SetBinding(HorizontalAnchoredCategorySeries.ValueMemberPathProperty,
                                    new Binding(YMemberPath) { Source = seriesSource });

                                category.SetBinding(HorizontalAnchoredCategorySeries.ItemsSourceProperty,
                                    new Binding(ItemsSourcePath) { Source = seriesSource });
                            }

                            if (shouldRenewAxes)
                            {
                                if (category.XAxis != null)
                                    _owner.Axes.Remove(category.XAxis);

                                if (category.YAxis != null)
                                    _owner.Axes.Remove(category.YAxis);

                                if (!clearOnly)
                                {
                                    CategoryXAxis xAxis = new CategoryXAxis();
                                    xAxis.SetBinding(CategoryXAxis.ItemsSourceProperty,
                                        new Binding(ItemsSourcePath) { Source = seriesSource });
                                    xAxis.Label = "{" + seriesSource.GetType().GetProperty(XMemberPath).GetValue(seriesSource, null) + "}";

                                    NumericYAxis yAxis = new NumericYAxis();

                                    _owner.Axes.Add(xAxis);
                                    _owner.Axes.Add(yAxis);

                                    category.XAxis = xAxis;
                                    category.YAxis = yAxis;
                                }
                            }
                        }
                        break;
                    case SeriesType.ScatterSeries:
                    case SeriesType.ScatterLineSeries:
                        {
                            ScatterBase scatter = series as ScatterBase;
                            scatter.ClearValue(ScatterBase.XMemberPathProperty);
                            scatter.ClearValue(ScatterBase.YMemberPathProperty);
                            scatter.ClearValue(ScatterBase.ItemsSourceProperty);

                            if (!clearOnly)
                            {
                                scatter.SetBinding(ScatterBase.XMemberPathProperty,
                                    new Binding(XMemberPath) { Source = seriesSource });

                                scatter.SetBinding(ScatterBase.YMemberPathProperty,
                                    new Binding(YMemberPath) { Source = seriesSource });

                                scatter.SetBinding(ScatterBase.ItemsSourceProperty,
                                    new Binding(ItemsSourcePath) { Source = seriesSource });
                            }


                            if (shouldRenewAxes)
                            {
                                if (scatter.XAxis != null)
                                    _owner.Axes.Remove(scatter.XAxis);

                                if (scatter.YAxis != null)
                                    _owner.Axes.Remove(scatter.YAxis);

                                if (!clearOnly)
                                {
                                    NumericXAxis xAxis = new NumericXAxis();
                                    NumericYAxis yAxis = new NumericYAxis();

                                    _owner.Axes.Add(xAxis);
                                    _owner.Axes.Add(yAxis);

                                    scatter.XAxis = xAxis;
                                    scatter.YAxis = yAxis;
                                }
                            }
                        }
                        break;

                    case SeriesType.ScatterContourSeries:
                        {
                            ScatterContourSeries scatterContour = series as ScatterContourSeries;
                            scatterContour.ClearValue(ScatterTriangulationSeries.XMemberPathProperty);
                            scatterContour.ClearValue(ScatterTriangulationSeries.YMemberPathProperty);
                            scatterContour.ClearValue(ScatterContourSeries.ValueMemberPathProperty);
                            scatterContour.ClearValue(ScatterTriangulationSeries.ItemsSourceProperty);

                            if (!clearOnly)
                            {
                                scatterContour.SetBinding(ScatterTriangulationSeries.XMemberPathProperty,
                                    new Binding(XMemberPath) { Source = seriesSource });

                                scatterContour.SetBinding(ScatterTriangulationSeries.YMemberPathProperty,
                                    new Binding(YMemberPath) { Source = seriesSource });

                                scatterContour.SetBinding(ScatterContourSeries.ValueMemberPathProperty,
                                   new Binding(ValueMemberPath) { Source = seriesSource });

                                scatterContour.SetBinding(ScatterTriangulationSeries.ItemsSourceProperty,
                                    new Binding(ItemsSourcePath) { Source = seriesSource });
                            }


                            if (shouldRenewAxes)
                            {
                                if (scatterContour.XAxis != null)
                                    _owner.Axes.Remove(scatterContour.XAxis);

                                if (scatterContour.YAxis != null)
                                    _owner.Axes.Remove(scatterContour.YAxis);

                                if (!clearOnly)
                                {
                                    NumericXAxis xAxis = new NumericXAxis();
                                    NumericYAxis yAxis = new NumericYAxis();


                                    _owner.Axes.Add(xAxis);
                                    _owner.Axes.Add(yAxis);

                                    scatterContour.XAxis = xAxis;
                                    scatterContour.YAxis = yAxis;
                                    // scatterContour.ValueMemberPath = 
                                }
                            }
                            ;
                        }
                        break;

                    default:
                        break;
                }

            }

        }

        #endregion

        #region Base Overrides

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            switch (e.Property.Name)
            {
                case SeriesSourcePropertyName:
                    {
                        if (e.OldValue != null
                            && e.OldValue is INotifyCollectionChanged)
                            (e.OldValue as INotifyCollectionChanged).CollectionChanged -= SeriesBinderInfo_CollectionChanged;
                        if (e.NewValue != null
                            && e.NewValue is INotifyCollectionChanged)
                            (e.NewValue as INotifyCollectionChanged).CollectionChanged += SeriesBinderInfo_CollectionChanged;

                        GenerateSeries();
                    }
                    break;
                case XMemberPathPropertyName:
                case YMemberPathPropertyName:
                case ValueMemberPathPropertyName:
                case TypePathPropertyName:
                    {
                        if (SeriesSource != null)
                            GenerateSeries();
                    }
                    break;
                default:
                    break;
            }
            base.OnPropertyChanged(e);
        }

        #endregion
    }

    #endregion

    #region View Model
    public class MainViewModel : PropertyChangedNotifier
    {
        private ObservableCollection<SeriesViewModel> seriesSource;
        private ObservableCollection<SeriesViewModel> seriesSource2;

        public MainViewModel()
        {
            SeriesSource = new ObservableCollection<SeriesViewModel>
            {
                new SeriesViewModel
                {
                    Source = ChartData.GenerateData(10),
                    Type = SeriesType.ColumnSeries,
                    XPath = "Date",
                    YPath = "Value",
                },
                new SeriesViewModel
                {
                    Source = ChartData.GenerateData(22),
                    Type = SeriesType.LineSeries,
                    XPath = "Label",
                    YPath = "Value",
                },

                new SeriesViewModel
                {
                    Source = ChartData.GenerateData(20),
                    Type = SeriesType.ScatterSeries,
                    XPath = "Index",
                    YPath = "Value",
                },
                new SeriesViewModel
                {
                    Source = ChartData.GenerateData(15),
                    Type = SeriesType.ScatterLineSeries,
                    XPath = "Index",
                    YPath = "Value",
                },
            };

            SeriesSource2 = new ObservableCollection<SeriesViewModel>();
        }

        public ObservableCollection<SeriesViewModel> SeriesSource
        {
            get { return seriesSource; }
            set { seriesSource = value; OnPropertyChagned("SeriesSource"); }
        }

        public ObservableCollection<SeriesViewModel> SeriesSource2
        {
            get { return seriesSource2; }
            set { seriesSource2 = value; OnPropertyChagned("SeriesSource2"); }
        }

        public ICommand AddSeries
        {
            get
            {
                return new RelayCommand<object>(
                    new Action<object>(
                        (obj) =>
                        {
                            SeriesSource2.Add(
                                new SeriesViewModel
                                {
                                    Source = ChartData.GenerateData(10),
                                    Type = SeriesType.ScatterContourSeries,
                                    XPath = "Index",
                                    YPath = "Index",
                                    ValueMemberPath = "Value"
                                });

                            SeriesSource.Add(
                                new SeriesViewModel
                                {
                                    Source = ChartData.GenerateData(10),
                                    Type = SeriesType.ScatterLineSeries,
                                    XPath = "Index",
                                    YPath = "Value",
                                    ValueMemberPath = "Value"
                                });

                        }));



            }
        }

        public ICommand RemoveSeries
        {
            get
            {
                return new RelayCommand<object>(
                    new Action<object>(
                        (obj) =>
                        {
                            if (SeriesSource.Count > 0)
                                SeriesSource.RemoveAt(0);
                        }));
            }
        }

        public ICommand ClearSeries
        {
            get
            {
                return new RelayCommand<object>(
                    new Action<object>(
                        (obj) =>
                        {
                            SeriesSource.Clear();
                        }));
            }
        }

        public ICommand ResetSeries
        {
            get
            {
                return new RelayCommand<object>(
                    new Action<object>(
                        (obj) =>
                        {
                            SeriesSource = new ObservableCollection<SeriesViewModel>
                            {
                                new SeriesViewModel
                                {
                                    Source = ChartData.GenerateData(10),
                                    Type = SeriesType.ColumnSeries,
                                    XPath = "Date",
                                    YPath = "Value",
                                },
                                new SeriesViewModel
                                {
                                    Source = ChartData.GenerateData(22),
                                    Type = SeriesType.LineSeries,
                                    XPath = "Label",
                                    YPath = "Value",
                                },

                                new SeriesViewModel
                                {
                                    Source = ChartData.GenerateData(20),
                                    Type = SeriesType.ScatterSeries,
                                    XPath = "Index",
                                    YPath = "Value",
                                },
                                new SeriesViewModel
                                {
                                    Source = ChartData.GenerateData(15),
                                    Type = SeriesType.ScatterLineSeries,
                                    XPath = "Index",
                                    YPath = "Value",
                                },
                            };
                        }));
            }
        }
    }

    public class SeriesViewModel : PropertyChangedNotifier
    {
        private SeriesType type;
        public SeriesType Type
        {
            get { return type; }
            set { type = value; OnPropertyChagned("Type"); }
        }

        private IEnumerable source;
        public IEnumerable Source
        {
            get { return source; }
            set { source = value; OnPropertyChagned("Source"); }
        }

        private string xPath;
        public string XPath
        {
            get { return xPath; }
            set { xPath = value; OnPropertyChagned("XPath"); }
        }

        private string yPath;
        public string YPath
        {
            get { return yPath; }
            set { yPath = value; OnPropertyChagned("XPath"); }
        }

        private string valueMemberPath;
        public string ValueMemberPath
        {
            get { return valueMemberPath; }
            set { valueMemberPath = value; OnPropertyChagned("ValueMemberPath"); }
        }

    }

    public class ChartData
    {
        public DateTime Date { get; set; }
        public int Index { get; set; }
        public string Label { get; set; }
        public double Value { get; set; }

        public static ObservableCollection<ChartData> GenerateData(int count)
        {
            ObservableCollection<ChartData> data = new ObservableCollection<ChartData>();

            Random r = new Random();

            ChartData data0 = new ChartData
            {
                Date = DateTime.Now,
                Index = 0,
                Value = r.Next(20, 40),
                Label = "Item 0"
            };

            data.Add(data0);

            for (int i = 1; i < count; i++)
            {
                ChartData dat = new ChartData
                {
                    Date = DateTime.Now.AddDays(i),
                    Index = i,
                    Label = "Item " + i,
                };

                if (r.NextDouble() > .5)
                    dat.Value = data[i - 1].Value + r.NextDouble();
                else
                    dat.Value = data[i - 1].Value - r.NextDouble();

                data.Add(dat);
            }

            return data;
        }
    }

    public class PropertyChangedNotifier : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChagned(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

    public enum SeriesType
    {
        LineSeries,
        ColumnSeries,
        ScatterSeries,
        ScatterLineSeries,
        ScatterContourSeries
    }

    public class RelayCommand<T> : ICommand
    {

        #region Declarations

        readonly Predicate<T> _canExecute;
        readonly Action<T> _execute;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="RelayCommand&lt;T&gt;"/> class and the command can always be executed.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        public RelayCommand(Action<T> execute)
            : this(execute, null)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RelayCommand&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        /// <param name="canExecute">The execution status logic.</param>
        public RelayCommand(Action<T> execute, Predicate<T> canExecute)
        {

            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }

        #endregion

        #region ICommand Members

        public event EventHandler CanExecuteChanged
        {
            add
            {

                if (_canExecute != null)
                    CommandManager.RequerySuggested += value;
            }
            remove
            {

                if (_canExecute != null)
                    CommandManager.RequerySuggested -= value;
            }
        }

        [DebuggerStepThrough]
        public virtual Boolean CanExecute(Object parameter)
        {
            return _canExecute == null ? true : _canExecute((T)parameter);
        }

        public virtual void Execute(Object parameter)
        {
            _execute((T)parameter);
        }

        #endregion
    }

    #endregion

}