예제 #1
0
        public static void ConvertItemValueFromV011(JObject item, int dtdId, ref PreValueCollection preValues)
        {
            var contentTypeAlias = GetContentTypeAliasFromItem(item);

            if (contentTypeAlias != null)
            {
                // the item is already in >v0.1.1 format
                return;
            }

            // old style (v0.1.1) data, let's attempt a conversion
            // - get the prevalues (if they're not loaded already)
            preValues = preValues ?? GetPreValuesCollectionByDataTypeId(dtdId);

            // - convert the prevalues (if necessary)
            ConvertPreValueCollectionFromV011(preValues);

            // - get the content types prevalue as JArray
            var preValuesAsDictionary = preValues.PreValuesAsDictionary.ToDictionary(x => x.Key, x => x.Value.Value);

            if (!preValuesAsDictionary.ContainsKey(ContentTypesPreValueKey) || string.IsNullOrEmpty(preValuesAsDictionary[ContentTypesPreValueKey]) != false)
            {
                return;
            }

            var preValueContentTypes = JArray.Parse(preValuesAsDictionary[ContentTypesPreValueKey]);

            if (preValueContentTypes.Any())
            {
                // the only thing we can really do is assume that the item is the first available content type
                item[NestedContentPropertyEditor.ContentTypeAliasPropertyKey] = preValueContentTypes.First().Value <string>("ncAlias");
            }
        }
예제 #2
0
        private static string contentReplace(string content, IContentBase entity)
        {
            var    ptypes          = entity.PropertyTypes;
            string contenttypename = ApplicationContext.Current.Services.EntityService.Get(entity.ContentTypeId, true).Name;

            foreach (var ptype in ptypes)
            {
                PreValueCollection coll = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(ptype.DataTypeDefinitionId);
                if (coll.PreValuesAsDictionary.Count == 0)
                {
                    string value = entity.GetValue <string>(ptype.Alias);

                    content = content.Replace("{{" + contenttypename + "." + ptype.Alias + "}}", entity.GetValue <string>(ptype.Alias));
                }
                else
                {
                    foreach (var item in coll.PreValuesAsDictionary)
                    {
                        var kk = entity.GetValue <int>(ptype.Alias);
                        if (item.Value.Id.Equals(entity.GetValue <int>(ptype.Alias)))
                        {
                            string strval = item.Value.Value;
                            content = content.Replace("{{" + contenttypename + "." + ptype.Alias + "}}", strval);
                        }
                    }
                }
            }
            return(content);
        }
예제 #3
0
        private ArchetypePreValue GetArchetypePreValueFromPreValuesCollection(PreValueCollection dataTypePreValues)
        {
            var preValueAsString = dataTypePreValues.PreValuesAsDictionary.First().Value.Value;
            var preValue         = JsonConvert.DeserializeObject <ArchetypePreValue>(preValueAsString, _jsonSettings);

            return(preValue);
        }
예제 #4
0
        public IEnumerable <ValidationResult> Validate(object value, PreValueCollection preValues, PropertyEditor editor)
        {
            //now check the file type
            var asJson = value as JObject;

            if (asJson == null)
            {
                yield break;
            }
            if (asJson["selectedFiles"] == null)
            {
                yield break;
            }
            var fileNames = asJson["selectedFiles"].ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var fileName in fileNames)
            {
                if (ValidateFileExtension(fileName) == false)
                {
                    yield return(new ValidationResult(ui.Text("errors", "dissallowedMediaType"),
                                                      new[]
                    {
                        //we only store a single value for this editor so the 'member' or 'field'
                        // we'll associate this error with will simply be called 'value'
                        "value"
                    }));
                }
            }
        }
예제 #5
0
        public static string GetRowOptionsDocType(PreValueCollection preValueCollection, string cellId)
        {
            var preValueDict = preValueCollection.PreValuesAsDictionary.ToDictionary(x => x.Key, x => x.Value.Value);

            // Check the grid config
            if (preValueDict.ContainsKey("gridConfig"))
            {
                var gridConfig = JsonConvert.DeserializeObject <Dictionary <string, Dictionary <string, object> > >(
                    preValueDict["gridConfig"].ToString(CultureInfo.InvariantCulture));

                if (gridConfig != null && gridConfig.ContainsKey(cellId) && gridConfig[cellId].ContainsKey("rowOptionsDocType"))
                {
                    return(gridConfig[cellId]["rowOptionsDocType"].ToString());
                }
            }

            // Check the default config
            if (preValueDict.ContainsKey("defaultConfig"))
            {
                var defaultConfig = JsonConvert.DeserializeObject <Dictionary <string, object> >(
                    preValueDict["defaultConfig"].ToString(CultureInfo.InvariantCulture));

                if (defaultConfig != null && defaultConfig.ContainsKey("rowOptionsDocType"))
                {
                    return(defaultConfig["rowOptionsDocType"].ToString());
                }
            }

            return(null);
        }
예제 #6
0
            private EmbeddedContentPropertyDisplay GetProperty(PropertyType propertyType, object value)
            {
                var property = new EmbeddedContentPropertyDisplay
                {
                    Editor      = propertyType.PropertyEditorAlias,
                    Label       = UmbracoDictionaryTranslate(propertyType.Name),
                    Description = UmbracoDictionaryTranslate(propertyType.Description),
                    Alias       = propertyType.Alias,
                    Value       = value
                };

                PropertyEditor propertyEditor = _propertyEditorResolver.GetByAlias(propertyType.PropertyEditorAlias);

                PreValueCollection preValues = _dataTypeService.GetPreValuesCollectionByDataTypeId(propertyType.DataTypeDefinitionId);

                property.Value = propertyEditor.ValueEditor.ConvertDbToEditor(
                    new Property(propertyType, value?.ToString()),
                    propertyType,
                    _dataTypeService
                    );


                propertyEditor.ValueEditor.ConfigureForDisplay(preValues);

                property.Config               = propertyEditor.PreValueEditor.ConvertDbToEditor(propertyEditor.DefaultPreValues, preValues);
                property.View                 = propertyEditor.ValueEditor.View;
                property.HideLabel            = propertyEditor.ValueEditor.HideLabel;
                property.Validation.Mandatory = propertyType.Mandatory;
                property.Validation.Pattern   = propertyType.ValidationRegExp;

                return(property);
            }
            public IEnumerable <ValidationResult> Validate(object value, PreValueCollection preValues, PropertyEditor editor)
            {
                var json = value as JArray;

                if (json == null)
                {
                    yield break;
                }

                //get all values in the array that are not empty (we'll remove empty values when persisting anyways)
                var groupedValues = json.OfType <JObject>()
                                    .Where(jItem => jItem["value"] != null)
                                    .Select((jItem, index) => new { value = jItem["value"].ToString(), index = index })
                                    .Where(asString => asString.value.IsNullOrWhiteSpace() == false)
                                    .GroupBy(x => x.value);

                foreach (var g in groupedValues.Where(g => g.Count() > 1))
                {
                    yield return(new ValidationResult("The value " + g.Last().value + " must be unique", new[]
                    {
                        //we'll make the server field the index number of the value so it can be wired up to the view
                        "item_" + g.Last().index.ToInvariantString()
                    }));
                }
            }
예제 #8
0
        public static T Map <T>(this PreValueCollection preValues)
            where T : class, new()
        {
            var preValuesDictionary = preValues.PreValuesAsDictionary;

            return(preValuesDictionary.Map <T>());
        }
예제 #9
0
        public IEnumerable <ValidationResult> Validate(object value, PreValueCollection preValues, PropertyEditor editor)
        {
            var results = new List <ValidationResult>();

            var model = JsonConvert.DeserializeObject <PropertyListValue>(value?.ToString());

            if (model == null)
            {
                return(results);
            }

            bool getIntValue(string alias, out int number)
            {
                number = 0;
                return(preValues.PreValuesAsDictionary.ContainsKey(alias) &&
                       int.TryParse(preValues.PreValuesAsDictionary[alias].Value, out number) &&
                       number > 0);
            }

            if (preValues.IsDictionaryBased)
            {
                var dict = preValues.PreValuesAsDictionary;
                if (getIntValue(PreValueKeys.MinItems, out int minItems) && model.Values.Count < minItems)
                {
                    results.Add(new ValidationResult($"There are {model.Values.Count} items in the list, when the minimum is set to {minItems}."));
                }

                if (getIntValue(PreValueKeys.MaxItems, out int maxItems) && model.Values.Count > maxItems)
                {
                    results.Add(new ValidationResult($"There are {model.Values.Count} items in the list, when the maximum is set to {maxItems}."));
                }
            }

            var meta = GetInnerPropertyMetaData(model.DataTypeGuid);

            if (meta == null)
            {
                return(results);
            }

            var validators = meta.Item3;

            if (validators == null || validators.Any() == false)
            {
                return(results);
            }

            foreach (var itemValue in model.Values)
            {
                // TODO: Consider what Mandatory and RegExp mean in the context of Property List, and how they should be handled.

                foreach (var validator in validators)
                {
                    results.AddRange(validator.Validate(itemValue, meta.Item1, meta.Item2));
                }
            }

            return(results);
        }
예제 #10
0
 /// <summary>
 /// Used when configured as an IPropertyValidator
 /// </summary>
 /// <param name="value"></param>
 /// <param name="preValues"></param>
 /// <param name="editor"></param>
 /// <returns></returns>
 public IEnumerable <ValidationResult> Validate(object value, PreValueCollection preValues, PropertyEditor editor)
 {
     if (_regex == null)
     {
         throw new InvalidOperationException("This validator is not configured as a " + typeof(IPropertyValidator));
     }
     return(Validate(value, _regex, preValues, editor));
 }
 /// <summary>
 /// This is called to configure the editor for display with it's prevalues, useful when properties need to change dynamically
 /// depending on what is in the pre-values.
 /// </summary>
 /// <param name="preValues"></param>
 /// <remarks>
 /// This cannot be used to change the value being sent to the editor, ConfigureEditor will be called *after* ConvertDbToEditor, pre-values
 /// should not be used to modify values.
 /// </remarks>
 public virtual void ConfigureForDisplay(PreValueCollection preValues)
 {
     if (preValues == null)
     {
         throw new ArgumentNullException("preValues");
     }
     _preVals = preValues;
 }
예제 #12
0
        public static string GetMetaDataDocType(PreValueCollection preValueCollection)
        {
            var preValueDict = preValueCollection.PreValuesAsDictionary.ToDictionary(x => x.Key, x => x.Value.Value);

            return(preValueDict.ContainsKey("metaDataDocType")
                                ? preValueDict["metaDataDocType"]
                                : "");
        }
예제 #13
0
        public override void ConfigureForDisplay(PreValueCollection preValues)
        {
            base.ConfigureForDisplay(preValues);

            if (preValues.PreValuesAsDictionary.ContainsKey(PreValueKeys.HideLabel))
            {
                HideLabel = preValues.PreValuesAsDictionary[PreValueKeys.HideLabel].Value == "1";
            }
        }
예제 #14
0
 private EmbeddedContentConfig GetConfig(int dataTypeId)
 {
     using (_profilingLogger.DebugDuration <EmbeddedContentValueConverter>($"GetConfig({dataTypeId})"))
     {
         PreValueCollection preValues      = _dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId);
         PreValue           configPreValue = preValues.PreValuesAsDictionary["embeddedContentConfig"];
         return(JsonConvert.DeserializeObject <EmbeddedContentConfig>(configPreValue.Value));
     }
 }
예제 #15
0
        public override void ConfigureForDisplay(PreValueCollection preValues)
        {
            base.ConfigureForDisplay(preValues);

            if (preValues.PreValuesAsDictionary.ContainsKey(InnerContentConstants.HideLabelPreValueKey))
            {
                HideLabel = preValues.PreValuesAsDictionary[InnerContentConstants.HideLabelPreValueKey].Value == "1";
            }
        }
예제 #16
0
        private string GetValue(PreValueCollection preValues, string key)
        {
            PreValue preValue;

            if (!preValues.PreValuesAsDictionary.TryGetValue(key, out preValue))
            {
                return(null);
            }

            return(preValue.Value);
        }
예제 #17
0
 public static int GetPreValueIdByValue(this PreValueCollection preValue, string value)
 {
     try
     {
         return(preValue.PreValuesAsDictionary.Where(b => b.Value.Value == value).FirstOrDefault().Value.Id);
     }
     catch
     {
         return(-1);
     }
 }
예제 #18
0
        public static int?getPrevalueId(string dataTypeName, string dataTypeValue)
        {
            // Instantiate datatype service
            IDataTypeService dtService = ApplicationContext.Current.Services.DataTypeService;

            // Obtain prevalue collection from datatypes
            IDataTypeDefinition dtDefinition = dtService.GetDataTypeDefinitionByName(dataTypeName);
            PreValueCollection  pvCollection = dtService.GetPreValuesCollectionByDataTypeId(dtDefinition.Id);

            return(pvCollection.PreValuesAsDictionary.FirstOrDefault(preValue => string.Equals(preValue.Value.Value, dataTypeValue)).Value.Id);
        }
            public override void ConfigureForDisplay(PreValueCollection preValues)
            {
                base.ConfigureForDisplay(preValues);

                if (preValues.PreValuesAsDictionary.ContainsKey("hideLabel"))
                {
                    var boolAttempt = preValues.PreValuesAsDictionary["hideLabel"].Value.TryConvertTo <bool>();
                    if (boolAttempt.Success)
                    {
                        HideLabel = boolAttempt.Result;
                    }
                }
            }
예제 #20
0
        private void SetPreValueInternal(IDataTypeDefinition dataType, PreValueCollection preValues, string name, string newValue)
        {
            var dictionary = preValues.FormatAsDictionary();
            var existing   = dictionary.GetValueOrDefault(name);

            if (existing != null)
            {
                var oldValue = existing.Value;
                existing.Value = newValue;
                Logger.Log("DataType: '{0}', changed setting '{1}': '{2}' => '{3}'.", dataType.Name, name, oldValue, newValue);
                return;
            }

            preValues.PreValuesAsDictionary[name] = new PreValue(newValue);
            Logger.Log("DataType: '{0}', added setting '{1}': '{2}'.", dataType.Name, name, newValue);
        }
        private bool HasPrevalues(PreValueCollection preVals)
        {
            if (preVals.PreValuesAsDictionary["crops"] == null ||
                preVals.PreValuesAsDictionary["crops"].Value.IsNullOrWhiteSpace())
            {
                return(false);
            }

            try
            {
                var array = JsonConvert.DeserializeObject <JArray>(preVals.PreValuesAsDictionary["crops"].Value);
                return(array.Count > 0);
            }
            catch (Exception)
            {
                return(false);
            }
        }
예제 #22
0
        public static void ConvertPreValueCollectionFromV011(PreValueCollection preValueCollection)
        {
            if (preValueCollection == null)
            {
                return;
            }

            var persistedPreValuesAsDictionary = preValueCollection.PreValuesAsDictionary.ToDictionary(x => x.Key, x => x.Value.Value);

            // do we have a "docTypeGuid" prevalue and no "contentTypes" prevalue?
            if (persistedPreValuesAsDictionary.ContainsKey("docTypeGuid") == false || persistedPreValuesAsDictionary.ContainsKey(ContentTypesPreValueKey))
            {
                // the prevalues are already in >v0.1.1 format
                return;
            }

            // attempt to parse the doc type guid
            Guid guid;

            if (Guid.TryParse(persistedPreValuesAsDictionary["docTypeGuid"], out guid) == false)
            {
                // this shouldn't happen... but just in case.
                return;
            }

            // find the content type
            var contentType = ApplicationContext.Current.Services.ContentTypeService.GetAllContentTypes().FirstOrDefault(c => c.Key == guid);

            if (contentType == null)
            {
                return;
            }

            // add a prevalue in the format expected by the new (>0.1.1) content type picker/configurator
            preValueCollection.PreValuesAsDictionary[ContentTypesPreValueKey] = new PreValue(
                string.Format(@"[{{""ncAlias"": ""{0}"", ""ncTabAlias"": ""{1}"", ""nameTemplate"": ""{2}"", }}]",
                              contentType.Alias,
                              persistedPreValuesAsDictionary["tabAlias"],
                              persistedPreValuesAsDictionary["nameTemplate"]
                              )
                );
        }
예제 #23
0
        /// <summary>
        /// Gets the JSON configuration file from the property with the given alias, by reading it's data type's pre values.
        /// </summary>
        /// <param name="pageId">The of the page containing the PartialSorter.</param>
        /// <param name="propertyAlias">The PartialSorter property alias.</param>
        /// <returns>The loaded JSON configuration file.</returns>
        public static JObject GetConfiguration(int pageId, string propertyAlias)
        {
            JObject config = GetCachedConfig(JsonConfigs, pageId, propertyAlias);

            if (config == null)
            {
                ServiceContext  services       = ApplicationContext.Current.Services;
                IContentService contentService = services.ContentService;
                IContent        settingsPage   = contentService.GetById(pageId);

                PropertyType property = settingsPage.ContentType.PropertyTypes.FirstOrDefault(p => p.Alias == propertyAlias);

                if (property != null)
                {
                    PreValueCollection preValues = services.DataTypeService.GetPreValuesCollectionByDataTypeId(property.DataTypeDefinitionId);
                    PreValue           jsonConfigUrl;

                    if (preValues.PreValuesAsDictionary.TryGetValue("jsonConfigUrl", out jsonConfigUrl) && !String.IsNullOrWhiteSpace(jsonConfigUrl.Value))
                    {
                        string url = jsonConfigUrl.Value;

                        if (!url.StartsWith("~"))
                        {
                            url = String.Format("{0}{1}", url.StartsWith("/") ? "~" : "~/", url);
                        }

                        string json;

                        using (StreamReader sr = new StreamReader(HttpContext.Current.Server.MapPath(url)))
                        {
                            json = sr.ReadToEnd();
                        }

                        config = JObject.Parse(json);
                        SetCachedConfig(JsonConfigs, pageId, propertyAlias, config);
                    }
                }
            }

            return(config);
        }
        public IEnumerable <ValidationResult> Validate(object value, PreValueCollection preValues, PropertyEditor editor)
        {
            //don't validate if empty
            if (value == null || value.ToString().IsNullOrWhiteSpace())
            {
                yield break;
            }

            DateTime dt;

            if (DateTime.TryParse(value.ToString(), out dt) == false)
            {
                yield return(new ValidationResult(string.Format("The string value {0} cannot be parsed into a DateTime", value),
                                                  new[]
                {
                    //we only store a single value for this editor so the 'member' or 'field'
                    // we'll associate this error with will simply be called 'value'
                    "value"
                }));
            }
        }
예제 #25
0
        public static IContentType GetContentTypeFromPreValue(PreValueCollection preValues)
        {
            var preValuesDict = preValues.AsPreValueDictionary();

            Guid contentTypeGuid;

            if (!preValuesDict.ContainsKey("docTypeGuid") || !Guid.TryParse(preValuesDict["docTypeGuid"], out contentTypeGuid))
            {
                return(null);
            }

            var contentTypeAlias = ApplicationContext.Current.Services.ContentTypeService.GetAliasByGuid(Guid.Parse(preValuesDict["docTypeGuid"]));
            var contentType      = ApplicationContext.Current.Services.ContentTypeService.GetContentType(contentTypeAlias);

            if (contentType == null || contentType.PropertyTypes == null)
            {
                return(null);
            }

            return(contentType);
        }
예제 #26
0
            public override void ConfigureForDisplay(PreValueCollection preValues)
            {
                using (_profilingLogger.DebugDuration <EmbeddedContentPropertyEditor>("ConfigureForDisplay()"))
                {
                    List <IContentType> contentTypes = _contentTypeService.GetAllContentTypes().ToList();

                    PreValue configPreValue = preValues.PreValuesAsDictionary["embeddedContentConfig"];
                    JObject  config         = JObject.Parse(configPreValue.Value);
                    config["configureForDisplay"] = true;

                    foreach (var item in config["documentTypes"].ToList())
                    {
                        var contentType = contentTypes.FirstOrDefault(x => x.Alias == item["documentTypeAlias"].Value <string>());

                        if (contentType == null)
                        {
                            item.Remove();
                            continue;
                        }

                        if (string.IsNullOrEmpty(item.Value <string>("nameTemplate")))
                        {
                            PropertyType propertyType = contentType.CompositionPropertyGroups
                                                        .OrderBy(x => x.SortOrder)
                                                        .FirstOrDefault()
                                                        ?.PropertyTypes
                                                        .OrderBy(x => x.SortOrder)
                                                        .FirstOrDefault();

                            if (propertyType != null)
                            {
                                item["nameTemplate"] = $"{{{{{propertyType.Alias}}}}}";
                            }
                        }
                    }

                    configPreValue.Value = config.ToString();
                }
                base.ConfigureForDisplay(preValues);
            }
예제 #27
0
        internal ArchetypeModel DeserializeJsonToArchetype(string sourceJson, PreValueCollection dataTypePreValues)
        {
            try
            {
                var archetype = JsonConvert.DeserializeObject <ArchetypeModel>(sourceJson, _jsonSettings);

                try
                {
                    // Get list of configured properties and their types and map them to the deserialized archetype model
                    var preValue = GetArchetypePreValueFromPreValuesCollection(dataTypePreValues);
                    RetrieveAdditionalProperties(ref archetype, preValue);
                }
                catch (Exception ex)
                {
                }

                return(archetype);
            }
            catch
            {
                return(new ArchetypeModel());
            }
        }
예제 #28
0
        public void DropDownPreValueEditor_Format_Data_For_Editor()
        {
            var defaultVals = new Dictionary <string, object>();
            var persisted   = new PreValueCollection(new Dictionary <string, PreValue>
            {
                { "item1", new PreValue(1, "Item 1") },
                { "item2", new PreValue(2, "Item 2") },
                { "item3", new PreValue(3, "Item 3") }
            });

            var editor = new ValueListPreValueEditor();

            var result = editor.ConvertDbToEditor(defaultVals, persisted);

            Assert.AreEqual(1, result.Count);
            Assert.IsTrue(result.ContainsKey("items"));
            var items = result["items"] as IDictionary <int, IDictionary <string, object> >;

            Assert.IsNotNull(items);
            Assert.AreEqual("Item 1", items[1]["value"]);
            Assert.AreEqual("Item 2", items[2]["value"]);
            Assert.AreEqual("Item 3", items[3]["value"]);
        }
                public IEnumerable <ValidationResult> Validate(object value, PreValueCollection preValues, PropertyEditor editor)
                {
                    var json = value as JArray;

                    if (json == null)
                    {
                        yield break;
                    }

                    //validate each item which is a json object
                    for (var index = 0; index < json.Count; index++)
                    {
                        var i     = json[index];
                        var jItem = i as JObject;
                        if (jItem == null || jItem["value"] == null)
                        {
                            continue;
                        }

                        //NOTE: we will be removing empty values when persisting so no need to validate
                        var asString = jItem["value"].ToString();
                        if (asString.IsNullOrWhiteSpace())
                        {
                            continue;
                        }

                        int parsed;
                        if (int.TryParse(asString, out parsed) == false)
                        {
                            yield return(new ValidationResult("The value " + asString + " is not a valid number", new[]
                            {
                                //we'll make the server field the index number of the value so it can be wired up to the view
                                "item_" + index.ToInvariantString()
                            }));
                        }
                    }
                }
        public void Can_Deep_Clone()
        {
            var d = new PreValueCollection(new Dictionary <string, PreValue>
            {
                { "blah1", new PreValue(1, "test1", 1) },
                { "blah2", new PreValue(2, "test1", 3) },
                { "blah3", new PreValue(3, "test1", 2) }
            });

            var a = new PreValueCollection(new[]
            {
                new PreValue(1, "test1", 1),
                new PreValue(2, "test1", 3),
                new PreValue(3, "test1", 2)
            });

            var clone1 = (PreValueCollection)d.DeepClone();
            var clone2 = (PreValueCollection)a.DeepClone();

            Action <PreValueCollection, PreValueCollection> assert = (orig, clone) =>
            {
                Assert.AreNotSame(orig, clone);
                var oDic = orig.FormatAsDictionary();
                var cDic = clone.FormatAsDictionary();
                Assert.AreEqual(oDic.Keys.Count(), cDic.Keys.Count());
                foreach (var k in oDic.Keys)
                {
                    Assert.AreNotSame(oDic[k], cDic[k]);
                    Assert.AreEqual(oDic[k].Id, cDic[k].Id);
                    Assert.AreEqual(oDic[k].SortOrder, cDic[k].SortOrder);
                    Assert.AreEqual(oDic[k].Value, cDic[k].Value);
                }
            };

            assert(d, clone1);
            assert(a, clone2);
        }
예제 #31
0
 public ContentPropertyData(object value, PreValueCollection preValues, IDictionary<string, object> additionalData)
 {
     Value = value;
     PreValues = preValues;
     AdditionalData = new ReadOnlyDictionary<string, object>(additionalData);
 }