protected override void SourceObjectPropertyChanged(object sender, PropertyChangedEventArgs e)
 {
     base.SourceObjectPropertyChanged(sender, e);
     if (Source != null && e.PropertyName == GetCpvValuePropertyName())
     {
         if (string.IsNullOrEmpty(Source.CPVValue) && Source.Cp != null &&
             !string.IsNullOrEmpty(Source.Cp.CustomParamDefault))
         {
             Source.CPVValue = Source.Cp.CustomParamDefault;
             return;
         }
         Source.FormattedValue = CpvHelper.GetFormattedValue(Source);
     }
     OnNeedRefresh();
 }
        private CustomParamValue CreateItem(CustomParam cp, decimal?parentCpvId)
        {
            var cpv = (CustomParamValue)Activator.CreateInstance(typeof(T));

            cpv.CPVID              = --_cpvid;
            cpv.CustomParamCode    = cp.GetKey <string>();
            cpv.CPV2Entity         = CpEntity;
            cpv.CPVKey             = CpKey;
            cpv.CPVValue           = cp.CustomParamDefault;
            cpv.VCustomParamParent = cp.CustomParamParent;
            cpv.Cp                = cp;
            cpv.FormattedValue    = CpvHelper.GetFormattedValue(cpv);
            cpv.CPVParent         = parentCpvId;
            cpv.VCustomParamCount = cp.CustomParamCount;
            cpv.VCustomParamDesc  = cp.CustomParamDesc;
            return(cpv);
        }
        private bool OnSaveInternal(bool canSave)
        {
            if (!canSave)
            {
                return(true);
            }

            if (!ConnectionManager.Instance.AllowRequest())
            {
                return(false);
            }

            try
            {
                _isUpdating = true;
                WaitStart();

                var changes = GetChanges(Source, true);

                var relatedChanges = CollectRelatedParams(Source, changes);

                if (!Validation(relatedChanges))
                {
                    return(false);
                }

                var selectedItem = SelectedItems[0];

                if (ShouldUpdateSeparately)
                {
                    var uowFactory = IoC.Instance.Resolve <IUnitOfWorkFactory>();
                    using (var uow = uowFactory.Create(false))
                    {
                        try
                        {
                            uow.BeginChanges();
                            var mng = GetManager();
                            mng.SetUnitOfWork(uow);

                            var sources = Source.OrderByDescending(cpv => cpv.CPVParent, new SpecialComparer());
                            foreach (var cpv in sources)
                            {
                                var key = cpv.GetKey <decimal>();
                                if (key < 0)
                                {
                                    var item = cpv;

                                    if (!string.IsNullOrEmpty(cpv.CPVValue) || //Если были проставлены значения по умолчанию - сохраняем
                                        cpv.Cp.CUSTOMPARAMSAVEMODE || HasChanges(GetChanges(CpvHelper.GetChildsCpvByParentCpv <T>(sources, cpv, false), true)))
                                    {
                                        mng.Insert(ref item);

                                        item.Cp             = cpv.Cp;
                                        item.FormattedValue = CpvHelper.GetFormattedValue(item);
                                        SourceUpdate(item, cpv);
                                        var childs = sources.Where(i => i.CPVParent == key);
                                        foreach (var child in childs)
                                        {
                                            child.CPVParent = item.CPVID;
                                        }
                                    }
                                    else
                                    {
                                        cpv.AcceptChanges();
                                    }
                                }
                                else
                                {
                                    //Удаляем параметры, у которых не установлен CUSTOMPARAMSAVEMODE и CPVValue is null и нет деток
                                    if (string.IsNullOrEmpty(cpv.CPVValue) && !cpv.Cp.CUSTOMPARAMSAVEMODE &&
                                        CpvHelper.GetChildsCpvByParentCpv <T>(sources, cpv, false).Length == 0)
                                    {
                                        mng.Delete(cpv);
                                        cpv.AcceptChanges();
                                    }
                                    else if (cpv.IsDirty)
                                    {
                                        mng.Update(cpv);
                                    }
                                }
                            }

                            uow.CommitChanges();
                        }
                        catch
                        {
                            uow.RollbackChanges();
                            throw;
                        }
                    }
                }

                _hasAddCpv = false;
                if (selectedItem != null)
                {
                    SelectedItem = selectedItem;
                }
                OnSourceUpdated();
            }
            catch (Exception ex)
            {
                if (!ExceptionHandler(ex, ExceptionResources.ItemCantSave))
                {
                    throw;
                }
                return(false);
            }
            finally
            {
                _isUpdating = false;
                WaitStop();
            }

            return(true);
        }
        private List <T> GetEditModelSource(out double lastQueryExecutionTime)
        {
            lastQueryExecutionTime = 0;
            if (_cps != null)
            {
                _cps.Clear();
            }
            _cps = null;

            if (string.IsNullOrEmpty(CpEntity))
            {
                throw new DeveloperException("Property CpEntity is undefined.");
            }
            if (string.IsNullOrEmpty(CpKey))
            {
                throw new DeveloperException("Property CpKey is undefined.");
            }

            //Получаем список cpv
            var mto       = IoC.Instance.Resolve <IManagerForObject>();
            var modeltype = typeof(T);
            var mgrType   = mto.GetManagerByTypeName(modeltype.Name);

            if (mgrType == null)
            {
                throw new DeveloperException(string.Format("Unknown source type '{0}'.", modeltype.Name));
            }

            List <CustomParamValue> items;

            using (var mgr = IoC.Instance.Resolve(mgrType, null) as IBaseManager)
            {
                if (mgr == null)
                {
                    throw new DeveloperException(string.Format("Can't resolve IBaseManager by '{0}'.", mgrType.Name));
                }
                var cpvtype = typeof(CustomParamValue);
                items = mgr.GetFiltered(string.Format("{0} = '{1}' AND {2} = '{3}'",
                                                      SourceNameHelper.Instance.GetPropertySourceName(cpvtype, CustomParamValue.CPV2EntityPropertyName),
                                                      CpEntity,
                                                      SourceNameHelper.Instance.GetPropertySourceName(cpvtype, CustomParamValue.CPVKeyPropertyName),
                                                      CpKey), GetModeEnum.Partial)
                        .OfType <CustomParamValue>().ToList();
                lastQueryExecutionTime += mgr.LastQueryExecutionTime;
            }

            using (var mgr = IoC.Instance.Resolve <IBaseManager <CustomParam> >())
            {
                //Получаем список параметров для данного item.CustomParamCode с учетом манданта
                _cps = ((ICustomParamManager)mgr).GetCPByInstance(CpEntity, CpKey, null, CpSource, CpTarget).ToList();
                lastQueryExecutionTime += mgr.LastQueryExecutionTime;
            }

            //проверяем наличие родительских параметров в CP
            var badcps = ValidateParentCustomParam(_cps);

            if (badcps.Length > 0)
            {
                CustomParam[] cpall;
                using (var mgr = IoC.Instance.Resolve <IBaseManager <CustomParam> >())
                {
                    //Получаем список параметров для данного item.CustomParamCode без учета манданта
                    cpall =
                        mgr.GetFiltered(string.Format("{0} = '{1}'",
                                                      SourceNameHelper.Instance.GetPropertySourceName(typeof(CustomParam), CustomParam.CustomParam2EntityPropertyName), CpEntity), GetModeEnum.Partial)
                        .ToArray();
                    lastQueryExecutionTime += mgr.LastQueryExecutionTime;
                }
                foreach (var bcp in badcps)
                {
                    var parent = GetParentCustomParam(cpall, bcp);
                    if (parent == null)
                    {
                        throw new DeveloperException("Can't find parent for '{0}'.", bcp);
                    }

                    if (_cps.Any(p => p.GetKey <string>() == parent.GetKey <string>()))
                    {
                        continue;
                    }

                    parent.IsReadOnly = true;
                    _cps.Add(parent);
                }
            }

            if (_cps == null || !_cps.Any())
            {
                _errorMessage = string.IsNullOrEmpty(MandantCode)
                    ? "Проверьте привязку параметров к манданту."
                    : string.Format("Проверьте привязку параметров к манданту '{0}'.", MandantCode);
            }

            foreach (var item in items)
            {
                item.Cp             = _cps.FirstOrDefault(i => i.GetKey <string>() == item.CustomParamCode);
                item.FormattedValue = CpvHelper.GetFormattedValue(item);
            }

            // получим корневые элементы cp - они обязаны быть
            var rootElements = _cps.Where(i => string.IsNullOrEmpty(i.CustomParamParent)).ToArray();

            if (rootElements.Length == 0 && string.IsNullOrEmpty(_errorMessage))
            {
                throw new DeveloperException("Отсутствуют корневые элементы параметров!");
            }

            // добавим корневые cpv, которые отсутствуют
            foreach (var root in rootElements)
            {
                var exist = items.FirstOrDefault(i => i.CustomParamCode.EqIgnoreCase(root.GetKey <string>()));
                if (exist == null)
                {
                    items.Add(CreateItem(root, null));
                }
            }

            var rootCpvs = items.Where(i => i.CPVParent == null).ToArray();

            // проходим по всем корневым cpv и добираем отсутствущие элементы
            foreach (var cpv in rootCpvs)
            {
                CollectItems(cpv, _cps.ToArray(), items);
            }

            //cpv, которые не должны были быть показаны, но показываем
            var badcpvs = items.Where(cpv => cpv.Cp == null).ToArray();

            if (badcpvs.Any())
            {
                using (var mgr = IoC.Instance.Resolve <IBaseManager <CustomParam> >())
                {
                    foreach (var cpv in badcpvs)
                    {
                        var cp = mgr.Get(cpv.CustomParamCode);
                        lastQueryExecutionTime += mgr.LastQueryExecutionTime;
                        if (cp == null)
                        {
                            items.Remove(cpv);
                        }
                        else
                        {
                            cp.IsReadOnly = true;
                            cpv.Cp        = cp;
                            if (string.IsNullOrEmpty(cpv.CPVValue))
                            {
                                cpv.CPVValue = cp.CustomParamDefault;
                            }
                            cpv.FormattedValue = CpvHelper.GetFormattedValue(cpv);
                        }
                    }
                }
            }

            var result = new List <T>();

            items.ForEach(p =>
            {
                p.AcceptChanges();
                result.Add((T)p);
            });
            return(result);
        }