/// <summary>
        /// Initializes a new instance of the <see cref="DataFilterFieldSelector"/> class.
        /// </summary>
        /// <param name="pathSelector">
        /// The path selector.
        /// </param>
        /// <param name="availableMembers">
        /// The available members.
        /// </param>
        /// <param name="selectedMember">
        /// The selected member.
        /// </param>
        /// <param name="isExpanded">
        /// The is expanded.
        /// </param>
        public DataFilterFieldSelector(
            DataFilterFieldPathSelector pathSelector,
            IEnumerable<FieldPathPropertyDefinition> availableMembers,
            FieldPathPropertyDefinition selectedMember,
            bool isExpanded = false)
        {
            if (pathSelector == null)
                throw new ArgumentNullException("pathSelector");

            if (availableMembers == null)
                throw new ArgumentNullException("availableMembers");

            _pathSelector = pathSelector;
            _avalableMembers = availableMembers.ToArray();
            _selectedMember = selectedMember;
            _isExpanded = isExpanded;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="FieldPathPropertyDefinition"/> class.
        /// </summary>
        /// <param name="parentProperty">
        /// The parent property.
        /// </param>
        /// <param name="memberDefinition">
        /// The member definition.
        /// </param>
        public FieldPathPropertyDefinition(FieldPathPropertyDefinition parentProperty, IFilterMemberDefinition memberDefinition)
        {
            if (parentProperty == null)
                throw new ArgumentNullException("parentProperty");

            if (memberDefinition == null)
                throw new ArgumentNullException("memberDefinition");

            _parentProperty = parentProperty;
            _dataFilter = parentProperty.DataFilter;
            _memberDefinition = memberDefinition;

            var propertyPath = memberDefinition.MemberName;
            var property = ParentProperty;
            while (property != null)
            {
                propertyPath = property.SystemName + Constants.FilterDescriptorMemberSeparator + propertyPath;
                property = property.ParentProperty;
            }

            PropertyName = propertyPath;
            PropertyType = memberDefinition.MemberType;
            DisplayName = memberDefinition.DisplayName;
        }
        private void AddMemberSelectors(FieldPathPropertyDefinition propertyDefinition, bool isLast)
        {
            if (propertyDefinition.ParentProperty != null)
            {
                AddMemberSelectors(propertyDefinition.ParentProperty, false);
            }

            var availableMembers =
                AvailableMembers.Select(x => x.ItemPropertyDefinition)
                                .OfType<FieldPathPropertyDefinition>()
                                .Where(x => x.ParentProperty == propertyDefinition.ParentProperty);

            var memberSelector = new DataFilterFieldSelector(this, availableMembers, propertyDefinition, !isLast);

            MemberSelectors.Add(memberSelector);
        }
        /// <summary>
        /// Loads subfields.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/> that returns the subfield collection.
        /// </returns>
        public async Task<IEnumerable<FieldPathPropertyDefinition>> LoadSubfieldsAsync()
        {
            if (!_loaded)
            {
                var fields = await MemberDefinition.GetSubfieldsAsync();
                var propertyDefinitions = new List<FieldPathPropertyDefinition>();

                foreach (var field in fields)
                {
                    var propertyDefinition = new FieldPathPropertyDefinition(this, field);
                    propertyDefinitions.Add(propertyDefinition);
                }

                Subfields.AddRange(propertyDefinitions.OrderBy(x => x.DisplayName));
                DataFilter.ItemPropertyDefinitions.AddRange(Subfields);

                _loaded = true;
            }

            return Subfields;
        }
        private void SetupTreeViewField(FieldPathPropertyDefinition propertyDefinition, EditorCreatedEventArgs e)
        {
            var linkField = propertyDefinition.LinkFieldSystemName;
            if (linkField != Constants.IdColumnName)
            {
                linkField += Constants.IdColumnName;
            }

            var filter = new FilterDescriptor(linkField, FilterOperator.IsNotEqualTo, null, typeof(int));

            LoadReferenceItems(propertyDefinition.DeclaringProcessSystemName, propertyDefinition.SystemName, filter.ToJSON(), e, propertyDefinition.ReferencedFieldSystemName);
        }
        private void SetupCrossReferenceField(FieldPathPropertyDefinition propertyDefinition, EditorCreatedEventArgs e)
        {
            var crProcessName = propertyDefinition.ReferencedProcessSystemName;
            var displayField = propertyDefinition.ReferencedFieldSystemName;

            FilterDescriptor filterDescriptor = null;
            if (Constants.StateProcessName.Equals(crProcessName) && !string.IsNullOrEmpty(propertyDefinition.DeclaringProcessSystemName))
            {
                filterDescriptor = new FilterDescriptor(
                    Constants.ProcessFieldName,
                    FilterOperator.IsEqualTo,
                    propertyDefinition.DeclaringProcessSystemName,
                    typeof(string));
            }

            var filter = filterDescriptor == null ? string.Empty : filterDescriptor.ToJSON();

            LoadReferenceItems(propertyDefinition.DeclaringProcessSystemName, propertyDefinition.SystemName, filter, e, displayField);
        }
        private async void LoadReverseCrossReferenceItems(FieldPathPropertyDefinition propertyDefinition, EditorCreatedEventArgs e)
        {
            if (string.IsNullOrEmpty(propertyDefinition.ReferencedProcessSystemName))
            {
                return;
            }

            try
            {
                var displayField = propertyDefinition.ReferencedFieldSystemName;
                var filter = new FilterDescriptor(propertyDefinition.LinkFieldSystemName, FilterOperator.IsGreaterThan, 0, typeof(int));

                var infoList =
                    await
                    DynamicTypeManager.GetInfoListAsync<IInfoClass>(
                        propertyDefinition.ReferencedProcessSystemName,
                        int.MaxValue,
                        0,
                        filter.ToJSON(),
                        null,
                        new SortList { new SortDescriptor(displayField, SortDirection.Ascending) });

                var comboBox = e.Editor.FindChildByType<RadComboBox>();
                if (comboBox == null)
                {
                    return;
                }

                dataFilter.Tag = true;
                try
                {
                    comboBox.ItemsSource = infoList;
                    comboBox.SelectedValuePath = "Id";
                    Observable.FromEventPattern<SelectionChangedEventHandler, SelectionChangedEventArgs>(
                        handler => comboBox.SelectionChanged += handler,
                        handler => comboBox.SelectionChanged -= handler).SubscribeWeakly(this, OnComboBoxSelectionChanged);

                    if (infoList != null)
                    {
                        //comboBox.ItemTemplate = CreateTemplateForReferenceField((IInfoClass) infoList[0], displayField);
                        comboBox.DisplayMemberPath = string.Join(".", infoList.ElementType.GetFullPropertyPath(displayField));
                    }

                    var filterViewModel = (SimpleFilterViewModel)e.Editor.DataContext;
                    if (filterViewModel != null && filterViewModel.Descriptor != null)
                    {
                        var placeholder = filterViewModel.Descriptor.Value as IInfoClass;
                        if (placeholder != null)
                        {
                            comboBox.SelectedValue = placeholder.Id;
                        }
                    }
                }
                finally
                {
                    dataFilter.Tag = null;
                }
            }
            catch (DataPortalException ex)
            {
                PopupFactory.NotifyFailure(ex);
            }
        }
        private async void LoadCrossReferenceItems(FieldPathPropertyDefinition propertyDefinition, EditorCreatedEventArgs e)
        {
            if (string.IsNullOrEmpty(propertyDefinition.ReferencedProcessSystemName))
            {
                return;
            }

            var busyIndicator = e.Editor.FindChildByType<RadBusyIndicator>();
            if (busyIndicator != null)
            {
                busyIndicator.IsBusy = true;
            }

            try
            {
                string filterExpression = null;
                if (propertyDefinition.SystemName == Constants.CurrentStateColumnName)
                {
                    // If it's a CurrentState filter, show only declaring process states.
                    var filterDescriptor = new FilterDescriptor(
                        Constants.ProcessFieldName,
                        FilterOperator.IsEqualTo,
                        propertyDefinition.DeclaringProcessSystemName,
                        typeof(string));

                    filterExpression = filterDescriptor.ToJSON();
                }

                var displayFieldName = propertyDefinition.ReferencedFieldSystemName == "AqlDetail" ? Constants.AqlDisplayField : propertyDefinition.ReferencedFieldSystemName;

                var infoList =
                    await
                    DynamicTypeManager.GetInfoListAsync<IInfoClass>(
                        propertyDefinition.ReferencedProcessSystemName,
                        int.MaxValue,
                        0,
                        filterExpression,
                        null,
                        new SortList { new SortDescriptor(displayFieldName, SortDirection.Ascending) });

                var comboBox = e.Editor.FindChildByType<RadComboBox>();
                if (comboBox == null)
                {
                    return;
                }

                dataFilter.Tag = true;

                try
                {
                    comboBox.ItemsSource = infoList;
                    comboBox.SelectedValuePath = "Id";

                    Observable.FromEventPattern<SelectionChangedEventHandler, SelectionChangedEventArgs>(
                        handler => comboBox.SelectionChanged += handler,
                        handler => comboBox.SelectionChanged -= handler).SubscribeWeakly(this, OnComboBoxSelectionChanged);

                    if (infoList != null)
                    {
                        comboBox.DisplayMemberPath = string.Join(".", infoList.ElementType.GetFullPropertyPath(displayFieldName));
                    }

                    var filterViewModel = (SimpleFilterViewModel)e.Editor.DataContext;
                    if (filterViewModel != null && filterViewModel.Descriptor != null)
                    {
                        var placeholder = filterViewModel.Descriptor.Value as IInfoClass;
                        if (placeholder != null)
                        {
                            comboBox.SelectedValue = placeholder.Id;
                        }
                    }
                }
                finally
                {
                    dataFilter.Tag = null;
                }
            }
            catch (DataPortalException ex)
            {
                PopupFactory.NotifyFailure(ex);
            }
            finally
            {
                if (busyIndicator != null)
                {
                    busyIndicator.IsBusy = false;
                }
            }
        }