File: System\ServiceModel\Activities\Presentation\CorrelationDataDesigner.xaml.cs
Project: ndp\cdf\src\NetFx40\Tools\System.Activities.Core.Presentation\System.Activities.Core.Presentation.csproj (System.Activities.Core.Presentation)
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//----------------------------------------------------------------
namespace System.ServiceModel.Activities.Presentation
{
    using System.Activities;
    using System.Activities.Presentation;
    using System.Activities.Presentation.Model;
    using System.Collections.Generic;
    using System.Windows;
    using System.Activities.Presentation.View;
    using System.Windows.Input;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.Runtime;
    using System.Activities.Presentation.Hosting;
    using System.Windows.Controls;
    using System.Globalization;
    using System.Linq;
 
    internal partial class CorrelationDataDesigner 
    {
        const string KeyPrefix = "key";
                
        public static readonly DependencyProperty ActivityProperty = DependencyProperty.Register(
            "Activity", 
            typeof(ModelItem), 
            typeof(CorrelationDataDesigner), 
            new UIPropertyMetadata(OnActivityChanged));
 
        public static readonly DependencyProperty CorrelationInitializeDataProperty = DependencyProperty.Register(
            "CorrelationInitializeData", 
            typeof(ObservableCollection<CorrelationDataWrapper>), 
            typeof(CorrelationDataDesigner),
            new UIPropertyMetadata(OnCorrelationDataChanged));
 
        public static readonly DependencyProperty CorrelationHandleProperty = DependencyProperty.Register(
            "CorrelationHandle", 
            typeof(ModelItem), 
            typeof(CorrelationDataDesigner));
 
        public static readonly RoutedCommand AddNewDataCommand = new RoutedCommand("AddNewDataCommand", typeof(CorrelationDataDesigner));
 
        DataGridHelper correlationDataDGHelper;
 
        public ModelItem Activity
        {
            get { return (ModelItem)GetValue(ActivityProperty); }
            set { SetValue(ActivityProperty, value); }
        }
 
        public ObservableCollection<CorrelationDataWrapper> CorrelationInitializeData
        {
            get { return (ObservableCollection<CorrelationDataWrapper>)GetValue(CorrelationInitializeDataProperty); }
            set { SetValue(CorrelationInitializeDataProperty, value); }
        }
 
        public ModelItem CorrelationHandle
        {
            get { return (ModelItem)GetValue(CorrelationHandleProperty); }
            set { SetValue(CorrelationHandleProperty, value); }
        }
 
        public CorrelationDataDesigner()
        {
            this.InitializeComponent();
 
            //create data grid helper
            this.correlationDataDGHelper = new DataGridHelper(this.correlationInitializers, this);            
            //add binding to handle Add new entry clicks
            this.CommandBindings.Add(new CommandBinding(AddNewDataCommand, OnAddNewDataExecuted));
            //provide callback to add new row functionality
            this.correlationDataDGHelper.AddNewRowCommand = AddNewDataCommand;
            //add title for "add new row" button
            this.correlationDataDGHelper.AddNewRowContent = (string)this.FindResource("addNewEntry");                       
 
            CorrelationDataWrapper.Editor = this;
        }
 
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            this.Loaded += this.OnCorrelationDataDesignerLoaded;
        }
 
        void OnCorrelationDataDesignerLoaded(object sender, RoutedEventArgs e)
        {
            bool isReadOnly = this.Activity != null ? this.Activity.GetEditingContext().Items.GetValue<ReadOnlyState>().IsReadOnly : false;
            this.correlationInitializers.IsReadOnly = isReadOnly;
            this.correlationHandleETB.IsReadOnly = isReadOnly;
        }
 
        void OnExpressionTextBoxLoaded(object sender, RoutedEventArgs args)
        {
            ((ExpressionTextBox)sender).IsIndependentExpression = true;
        }
 
        //user clicked Add new data
        void OnAddNewDataExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            //generate unique dictionary key
            string keyName = this.CorrelationInitializeData.GetUniqueName<CorrelationDataWrapper>(KeyPrefix, item => item.Key);
            //create new key value pair and add it to the dictionary
            CorrelationDataWrapper wrapper = new CorrelationDataWrapper(keyName, null);
            this.CorrelationInitializeData.Add(wrapper);
            //begin row edit after adding new entry
            this.correlationDataDGHelper.BeginRowEdit(wrapper, this.correlationInitializers.Columns[1]);
        }
       
        static void OnActivityChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var item = e.NewValue as ModelItem;
            if (null != item && !item.IsAssignableFrom<InitializeCorrelation>())
            {
                Fx.Assert("CorrelationDataDesigner can only used to edit CorrelationData property of InitializeCorrelation activity");                
            }            
        }
 
        static void OnCorrelationDataChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as CorrelationDataDesigner).correlationInitializers.ItemsSource = e.NewValue as ObservableCollection<CorrelationDataWrapper>;
        }
 
        internal void CommitEdit()
        {
            if ((this.Activity != null) && (this.Activity.ItemType == typeof(InitializeCorrelation)))
            {
                using (ModelEditingScope scope = this.Activity.BeginEdit((string)this.FindResource("editCorrelationDataDescription")))
                {
                    this.Activity.Properties[InitializeCorrelationDesigner.CorrelationPropertyName].SetValue(this.CorrelationHandle);
                    ModelItemCollection correlationDataCollection = this.Activity.Properties[InitializeCorrelationDesigner.CorrelationDataPropertyName].Dictionary.Properties["ItemsCollection"].Collection;
                    correlationDataCollection.Clear();
                    foreach (CorrelationDataWrapper wrapper in this.CorrelationInitializeData)
                    {
                        correlationDataCollection.Add(new ModelItemKeyValuePair<string, InArgument<string>>
                            {
                                Key = wrapper.Key,
                                Value = wrapper.Value != null ? wrapper.Value.GetCurrentValue() as InArgument<string> : null
                            });
                    }
                    scope.Complete();
                }
            }
        }
 
        internal void ValidateKey(CorrelationDataWrapper wrapper, string oldKey)
        {
            string newKey = wrapper.Key;            
            if (string.IsNullOrEmpty(newKey))
            {
                ErrorReporting.ShowErrorMessage(string.Format(CultureInfo.CurrentCulture, System.Activities.Core.Presentation.SR.NullOrEmptyKeyName));
                wrapper.Key = oldKey;
            }
            else 
            {
                // At this point, the key of the entry has already been changed. If there are 
                // entries with duplicate keys, the number of those entries is greater than 1.
                // Thus, we only need to check the entry count.
                int entryCount = this.CorrelationInitializeData.Count(entry => entry.Key == newKey);
                if (entryCount > 1)
                {
                    ErrorReporting.ShowErrorMessage(string.Format(CultureInfo.CurrentCulture, System.Activities.Core.Presentation.SR.DuplicateKeyName, newKey));
                    wrapper.Key = oldKey;
                }
            }
        }
 
        void OnEditingControlLoaded(object sender, RoutedEventArgs args)
        {
            DataGridHelper.OnEditingControlLoaded(sender, args);
        }
 
        void OnEditingControlUnloaded(object sender, RoutedEventArgs args)
        {
            DataGridHelper.OnEditingControlUnloaded(sender, args);
        }
    }
 
    internal sealed class CorrelationDataWrapper : DependencyObject
    {
        public static readonly DependencyProperty KeyProperty =
            DependencyProperty.Register("Key", typeof(string), typeof(CorrelationDataWrapper), new UIPropertyMetadata(string.Empty, OnKeyChanged));
 
 
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(ModelItem), typeof(CorrelationDataWrapper));
 
        bool isValidating;
        public ModelItem Value
        {
            get { return (ModelItem)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
       
        public string Key
        {
            get { return (string)GetValue(KeyProperty); }
            set { SetValue(KeyProperty, value); }
        }
 
        public static CorrelationDataDesigner Editor
        {
            get;
            set;
        }
 
        public CorrelationDataWrapper()
        {
            throw FxTrace.Exception.AsError(new NotSupportedException());
        }
 
        internal CorrelationDataWrapper(string key, ModelItem value)            
        {
            //Skip validation when first populate the collection
            this.isValidating = true;
            this.Key = key;
            this.Value = value;
            this.isValidating = false;
        }
 
        static void OnKeyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            CorrelationDataWrapper wrapper = sender as CorrelationDataWrapper;
            if ((wrapper != null) && (!wrapper.isValidating))
            {                
                wrapper.isValidating = true;
                CorrelationDataWrapper.Editor.ValidateKey(wrapper, (string)e.OldValue);
                wrapper.isValidating = false;
            }
        }
    }
}