/// <summary>
        /// Loads the expression items.
        /// </summary>
        /// <param name="process">The process.</param>
        /// <param name="dataSources">The data sources.</param>
        /// <param name="sourceDataProcess">The source data process.</param>
        /// <param name="destinationListField">The destination list field.</param>
        /// <param name="destinationProcess">The destination process.</param>
        /// <param name="fieldMapping">The field mapping.</param>
        private async void LoadExpressionItems(
            IProcessEdit process,
            IEnumerable<DataTriggerMappingDataSourceRetriever> dataSources,
            ProcessInfo sourceDataProcess,
            FieldInfo destinationListField,
            ProcessInfo destinationProcess,
            DataTriggerFieldMappingEdit fieldMapping)
        {
            WindowManager.Value.ShowStatus(new Status { IsBusy = true });

            var expressions = new List<IExpressionObjectBase>();
            var newExpressions = new List<IExpressionObjectBase>();

            var syncContext = new NotifyClientAction(
                () =>
                    {
                        ExpressionDesigner.LoadFromExpressionObjects(expressions);
                        WindowManager.Value.ShowStatus(new Status());
                    });

            syncContext.OperationStarted();

            if (fieldMapping.ModificationType == DataTriggerModificationType.Link || fieldMapping.ModificationType == DataTriggerModificationType.Unlink)
            {
                var objectName = string.Format("sourceData.GetSourceItem(\"{0}\")", DataTriggerFieldMappingExpressionNames.SourceDataProcess);

                newExpressions.Add(CreateSourceItem(sourceDataProcess, DataTriggerFieldMappingExpressionNames.SourceDataProcess, sourceDataProcess.Name, objectName));
            }
            else
            {
                foreach (var dataSource in dataSources)
                {
                    var name = string.Format(CultureInfo.InvariantCulture, "{0} (source)", dataSource.SourceFieldName);
                    var objectName = string.Format("sourceData.GetSourceItem(\"{0}\")", dataSource.SourceName);
                    newExpressions.Add(CreateSourceItem(dataSource.SourceProcess, dataSource.SourceName, name, objectName));
                }

                newExpressions.Add(
                    CreateSourceItem(
                        destinationProcess,
                        DataTriggerFieldMappingExpressionNames.ModifiedItem,
                        string.Format("{0} (old)", destinationListField.Name),
                        ModifiedItemObjectName));
            }

            newExpressions.Add(CreateUserInfoSourceItem(DataTriggerFieldMappingExpressionNames.UserInfo));

            try
            {
                var systemParameters = await CreateSystemParametersItemAsync(DataTriggerFieldMappingExpressionNames.SystemParameters);
                if (systemParameters != null)
                {
                    newExpressions.Add(systemParameters);
                }
            }
            catch (DataPortalException)
            {
            }

            newExpressions.Add(CreateDestinationItem(destinationProcess, DataTriggerFieldMappingExpressionNames.DestinationItem, destinationListField.Name));

            UpdatePositions(newExpressions);

            if (!string.IsNullOrWhiteSpace(fieldMapping.Expression))
            {
                try
                {
                    var expressionsContainer = Serializer.Deserialize(fieldMapping.Expression);
                    expressions.AddRange(expressionsContainer.Expressions);
                }
                catch
                {
                    // Do nothing, new expressions will be used.
                }
            }

            UpdateStateList(process);

            UpdateStoredExpressions(expressions, newExpressions, syncContext);
            syncContext.OperationCompleted();
        }
        /// <summary>
        /// Opens the data trigger field mapping designer window.
        /// </summary>
        /// <param name="parentWindow">The parent window.</param>
        /// <param name="process">The process.</param>
        /// <param name="trigger">The trigger.</param>
        /// <param name="fieldMapping">The field mapping.</param>
        /// <param name="saveAction">The save action.</param>
        /// <param name="cancelAction">The cancel action.</param>
        /// <param name="removeAction">The remove action.</param>
        public void EditExpression(
            ITopLevelWindow parentWindow,
            IProcessEdit process,
            ProcessDataTriggerEdit trigger,
            DataTriggerFieldMappingEdit fieldMapping,
            Action saveAction,
            Action cancelAction,
            Action removeAction)
        {
            SaveAction = saveAction;
            CancelAction = cancelAction;
            RemoveAction = removeAction;

            ProcessEdit = process;
            KeyFieldsEnabled = fieldMapping.ModificationType != DataTriggerModificationType.Link
                               && fieldMapping.ModificationType != DataTriggerModificationType.Unlink;

            ExpressionDesigner.LoadFromExpressionObjects(new List<IExpressionObjectBase>());

            var criteria = new DataTriggerListFieldsMappingCriteria
                               {
                                   ModifiedProcessSystemName = trigger.ProcessToModifySystemName,
                                   DestinationFieldSystemName = fieldMapping.DestinationFieldSystemName
                               };

            var processFields = process.GetAllFields().ToArray();

            if (fieldMapping.ModificationType == DataTriggerModificationType.Link || fieldMapping.ModificationType == DataTriggerModificationType.Unlink)
            {
                if (string.IsNullOrEmpty(fieldMapping.SourceDataProcessName))
                {
                    PopupFactory.NotifyFailure("Source field is invalid. Please select a valid source field and try again.");
                    CancelCommand.Execute(null);
                    return;
                }

                criteria.SourceDataProcessName = fieldMapping.SourceDataProcessName;
            }
            else
            {
                foreach (var dataSource in fieldMapping.DataSources)
                {
                    var sourceField = processFields.FirstOrDefault(f => f.SystemName == dataSource.SourceFieldSystemName);

                    if (sourceField == null)
                    {
                        PopupFactory.NotifyFailure("Source field not found. Please select a valid source field and try again.");
                        CancelCommand.Execute(null);
                        return;
                    }

                    var requiredStep = (CrossRefRequiredStepEdit)sourceField.StepList.FirstOrDefault(s => s is CrossRefRequiredStepEdit);

                    if (requiredStep == null || !requiredStep.CrossRefProcessId.HasValue)
                    {
                        PopupFactory.NotifyFailure("Source field is invalid. Please select a valid source field and try again.");
                        CancelCommand.Execute(null);
                        return;
                    }

                    criteria.DataSourcesCriteria.Add(
                        new DataTriggerFieldMappingDataSourceCriteria
                        {
                            SourceName = dataSource.Name,
                            PublishedProcessId = requiredStep.CrossRefProcessId.Value,
                            SourceFieldName = sourceField.Name,
                            PropertyPath = dataSource.GetPropertyPath()
                        });
                }
            }

            WindowManager.Value.ShowStatus(new Status { IsBusy = true });

            DataTriggerMappingDataRetriever.GetDataTriggerMappingDataRetriever(
                criteria,
                result =>
                    {
                        WindowManager.Value.ShowStatus(new Status());
                        if (result.Error != null)
                        {
                            PopupFactory.NotifyFailure(result.Error);
                            CancelCommand.Execute(null);
                            return;
                        }

                        LoadExpressionItems(
                            process,
                            result.Object.DataSources,
                            result.Object.SourceDataProcess,
                            result.Object.DestinationListField,
                            result.Object.DestinationProcess,
                            fieldMapping);

                        _itemHashes = ExpressionDesigner.Diagram.Items.Select(x => x.GetHashCode()).ToList();

                        WindowManager.Value.ShowChildWindow(parentWindow, this);
                    });
        }