Merge remote-tracking branch 'origin/temp8' into temp8-3130-examine-indexing-variant-switching
# Conflicts: # src/Umbraco.Tests/Services/ContentServiceTests.cs
This commit is contained in:
@@ -1,35 +0,0 @@
|
||||
using System;
|
||||
using Umbraco.Core.Exceptions;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
internal class ActionMetadataAttribute : Attribute
|
||||
{
|
||||
public string Category { get; }
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor used to assign a Category, since no name is assigned it will try to be translated from the language files based on the action's alias
|
||||
/// </summary>
|
||||
/// <param name="category"></param>
|
||||
public ActionMetadataAttribute(string category)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(category)) throw new ArgumentNullOrEmptyException(nameof(category));
|
||||
Category = category;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor used to assign an explicit name and category
|
||||
/// </summary>
|
||||
/// <param name="category"></param>
|
||||
/// <param name="name"></param>
|
||||
public ActionMetadataAttribute(string category, string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(category)) throw new ArgumentNullOrEmptyException(nameof(category));
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
|
||||
Category = category;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,26 +44,6 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string DateTime = "Umbraco.DateTime";
|
||||
|
||||
/// <summary>
|
||||
/// DropDown List.
|
||||
/// </summary>
|
||||
public const string DropDownList = "Umbraco.DropDown";
|
||||
|
||||
/// <summary>
|
||||
/// DropDown List, Publish Keys.
|
||||
/// </summary>
|
||||
public const string DropdownlistPublishKeys = "Umbraco.DropdownlistPublishingKeys";
|
||||
|
||||
/// <summary>
|
||||
/// DropDown List Multiple.
|
||||
/// </summary>
|
||||
public const string DropDownListMultiple = "Umbraco.DropDownMultiple";
|
||||
|
||||
/// <summary>
|
||||
/// DropDown List Multiple, Publish Keys.
|
||||
/// </summary>
|
||||
public const string DropdownlistMultiplePublishKeys = "Umbraco.DropdownlistMultiplePublishKeys";
|
||||
|
||||
/// <summary>
|
||||
/// DropDown List.
|
||||
/// </summary>
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownMultiple, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownMultiple}", SortOrder = 2, UniqueId = new Guid("0b6a45e7-44ba-430d-9da5-4e46060b9e03"), Text = "Dropdown", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = new Guid("5046194e-4237-453c-a547-15db3a07c4e1"), Text = "Date Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = new Guid("bb5f57c9-ce2b-4bb9-b697-4caca783a805"), Text = "Radiobox", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -39, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-39", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownSingle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownSingle}", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = new Guid("0225af17-b302-49cb-9176-b9f35cab9c17"), Text = "Approved Color", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -36, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-36", SortOrder = 2, UniqueId = new Guid("e4d66c0f-b935-4200-81f0-025f7256b89a"), Text = "Date Picker with time", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultContentListView}", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
|
||||
@@ -139,6 +139,8 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
Chain<DropTaskTables>("{6A2C7C1B-A9DB-4EA9-B6AB-78E7D5B722A7}");
|
||||
Chain<FixLockTablePrimaryKey>("{77874C77-93E5-4488-A404-A630907CEEF0}");
|
||||
Chain<AddLogTableColumns>("{8804D8E8-FE62-4E3A-B8A2-C047C2118C38}");
|
||||
Chain<DropPreValueTable>("{23275462-446E-44C7-8C2C-3B8C1127B07D}");
|
||||
Chain<DropDownPropertyEditorsMigration>("{6B251841-3069-4AD5-8AE9-861F9523E8DA}");
|
||||
|
||||
//FINAL
|
||||
|
||||
|
||||
@@ -7,10 +7,11 @@ using NPoco;
|
||||
using Umbraco.Core.Migrations.Install;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
|
||||
public class DataTypeMigration : MigrationBase
|
||||
{
|
||||
public DataTypeMigration(IMigrationContext context)
|
||||
@@ -79,10 +80,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
|
||||
Database.Update(dataType);
|
||||
}
|
||||
|
||||
// drop preValues table
|
||||
// FIXME keep it around for now
|
||||
//Delete.Table("cmsDataTypePreValues");
|
||||
}
|
||||
|
||||
[TableName("cmsDataTypePreValues")]
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
public class DropDownPropertyEditorsMigration : MigrationBase
|
||||
{
|
||||
public DropDownPropertyEditorsMigration(IMigrationContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
//need to convert the old drop down data types to use the new one
|
||||
var oldDropDowns = Database.Fetch<DataTypeDto>(Sql()
|
||||
.Select<DataTypeDto>()
|
||||
.From<DataTypeDto>()
|
||||
.Where<DataTypeDto>(x => x.EditorAlias.Contains(".DropDown")));
|
||||
foreach (var dd in oldDropDowns)
|
||||
{
|
||||
//nothing to change if there is no config
|
||||
if (dd.Configuration.IsNullOrWhiteSpace()) continue;
|
||||
|
||||
ValueListConfiguration config;
|
||||
try
|
||||
{
|
||||
config = JsonConvert.DeserializeObject<ValueListConfiguration>(dd.Configuration);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error<DropDownPropertyEditorsMigration>(
|
||||
ex, "Invalid drop down configuration detected: \"{Configuration}\", cannot convert editor, values will be cleared",
|
||||
dd.Configuration);
|
||||
dd.Configuration = null;
|
||||
Database.Update(dd);
|
||||
continue;
|
||||
}
|
||||
|
||||
var propDataSql = Sql().Select<PropertyDataDto>().From<PropertyDataDto>()
|
||||
.InnerJoin<PropertyTypeDto>().On<PropertyTypeDto, PropertyDataDto>(x => x.Id, x => x.PropertyTypeId)
|
||||
.InnerJoin<DataTypeDto>().On<DataTypeDto, PropertyTypeDto>(x => x.NodeId, x => x.DataTypeId)
|
||||
.Where<PropertyTypeDto>(x => x.DataTypeId == dd.NodeId);
|
||||
|
||||
var propDatas = Database.Query<PropertyDataDto>(propDataSql);
|
||||
var toUpdate = new List<PropertyDataDto>();
|
||||
foreach (var propData in propDatas)
|
||||
{
|
||||
if (UpdatePropertyDataDto(propData, config))
|
||||
{
|
||||
//update later, we are iterating all values right now so no SQL can be run inside of this iteration (i.e. Query<T>)
|
||||
toUpdate.Add(propData);
|
||||
}
|
||||
}
|
||||
|
||||
//run the property data updates
|
||||
foreach (var propData in toUpdate)
|
||||
{
|
||||
Database.Update(propData);
|
||||
}
|
||||
|
||||
var requiresCacheRebuild = false;
|
||||
switch (dd.EditorAlias)
|
||||
{
|
||||
case string ea when ea.InvariantEquals("Umbraco.DropDown"):
|
||||
UpdateDataType(dd, config, false);
|
||||
break;
|
||||
case string ea when ea.InvariantEquals("Umbraco.DropdownlistPublishingKeys"):
|
||||
UpdateDataType(dd, config, false);
|
||||
requiresCacheRebuild = true;
|
||||
break;
|
||||
case string ea when ea.InvariantEquals("Umbraco.DropDownMultiple"):
|
||||
UpdateDataType(dd, config, true);
|
||||
break;
|
||||
case string ea when ea.InvariantEquals("Umbraco.DropdownlistMultiplePublishKeys"):
|
||||
UpdateDataType(dd, config, true);
|
||||
requiresCacheRebuild = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (requiresCacheRebuild)
|
||||
{
|
||||
//TODO: How to force rebuild the cache?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDataType(DataTypeDto dataType, ValueListConfiguration config, bool isMultiple)
|
||||
{
|
||||
dataType.EditorAlias = Constants.PropertyEditors.Aliases.DropDownListFlexible;
|
||||
var flexConfig = new
|
||||
{
|
||||
multiple = isMultiple,
|
||||
items = config.Items
|
||||
};
|
||||
dataType.DbType = ValueStorageType.Nvarchar.ToString();
|
||||
dataType.Configuration = JsonConvert.SerializeObject(flexConfig);
|
||||
Database.Update(dataType);
|
||||
}
|
||||
|
||||
private bool UpdatePropertyDataDto(PropertyDataDto propData, ValueListConfiguration config)
|
||||
{
|
||||
//Get the INT ids stored for this property/drop down
|
||||
int[] ids = null;
|
||||
if (!propData.VarcharValue.IsNullOrWhiteSpace())
|
||||
{
|
||||
ids = ConvertStringValues(propData.VarcharValue);
|
||||
}
|
||||
else if (!propData.TextValue.IsNullOrWhiteSpace())
|
||||
{
|
||||
ids = ConvertStringValues(propData.TextValue);
|
||||
}
|
||||
else if (propData.IntegerValue.HasValue)
|
||||
{
|
||||
ids = new[] { propData.IntegerValue.Value };
|
||||
}
|
||||
|
||||
//if there are INT ids, convert them to values based on the configured pre-values
|
||||
if (ids != null && ids.Length > 0)
|
||||
{
|
||||
//map the ids to values
|
||||
var vals = new List<string>();
|
||||
var canConvert = true;
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var val = config.Items.FirstOrDefault(x => x.Id == id);
|
||||
if (val != null)
|
||||
vals.Add(val.Value);
|
||||
else
|
||||
{
|
||||
Logger.Warn<DropDownPropertyEditorsMigration>(
|
||||
"Could not find associated data type configuration for stored Id {DataTypeId}", id);
|
||||
canConvert = false;
|
||||
}
|
||||
}
|
||||
if (canConvert)
|
||||
{
|
||||
propData.VarcharValue = string.Join(",", vals);
|
||||
propData.TextValue = null;
|
||||
propData.IntegerValue = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int[] ConvertStringValues(string val)
|
||||
{
|
||||
var splitVals = val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var intVals = splitVals
|
||||
.Select(x => int.TryParse(x, out var i) ? i : int.MinValue)
|
||||
.Where(x => x != int.MinValue)
|
||||
.ToArray();
|
||||
|
||||
//only return if the number of values are the same (i.e. All INTs)
|
||||
if (splitVals.Length == intVals.Length)
|
||||
return intVals;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
public class DropPreValueTable : MigrationBase
|
||||
{
|
||||
public DropPreValueTable(IMigrationContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
// drop preValues table
|
||||
if (TableExists("cmsDataTypePreValues"))
|
||||
Delete.Table("cmsDataTypePreValues").Do();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
public class DropdownListMultipleValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropDownListMultiple);
|
||||
|
||||
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
|
||||
=> typeof (IEnumerable<string>);
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
|
||||
=> PropertyCacheLevel.Element;
|
||||
|
||||
public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object source, bool preview)
|
||||
{
|
||||
var sourceString = (source ?? "").ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(sourceString))
|
||||
return Enumerable.Empty<string>();
|
||||
|
||||
var values =
|
||||
sourceString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim());
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
public class DropdownListMultipleWithKeysValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropdownlistMultiplePublishKeys);
|
||||
|
||||
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
|
||||
=> typeof (IEnumerable<int>);
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
|
||||
=> PropertyCacheLevel.Element;
|
||||
|
||||
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
if (source == null)
|
||||
return new int[] { };
|
||||
|
||||
var prevalueIds = source.ToString()
|
||||
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(p => p.Trim())
|
||||
.Select(int.Parse)
|
||||
.ToArray();
|
||||
|
||||
return prevalueIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
public class DropdownListValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropDownList);
|
||||
|
||||
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
|
||||
=> typeof (string);
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
|
||||
=> PropertyCacheLevel.Element;
|
||||
|
||||
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
return source?.ToString() ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
public class DropdownListWithKeysValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropdownlistPublishKeys);
|
||||
|
||||
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
|
||||
=> typeof (int);
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
|
||||
=> PropertyCacheLevel.Element;
|
||||
|
||||
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
var intAttempt = source.TryConvertTo<int>();
|
||||
if (intAttempt.Success)
|
||||
return intAttempt.Result;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,6 @@
|
||||
<Compile Include="Cache\SingleItemsOnlyRepositoryCachePolicy.cs" />
|
||||
<Compile Include="Cache\StaticCacheProvider.cs" />
|
||||
<Compile Include="Cache\TypedCacheRefresherBase.cs" />
|
||||
<Compile Include="CodeAnnotations\ActionMetadataAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\FriendlyNameAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoObjectTypeAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoUdiTypeAttribute.cs" />
|
||||
@@ -357,6 +356,8 @@
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\AddVariationTables1A.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\AddVariationTables2.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypeMigration.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\DropDownPropertyEditorsMigration.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\DropPreValueTable.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\DropTaskTables.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\FixLockTablePrimaryKey.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\LanguageColumns.cs" />
|
||||
@@ -1242,10 +1243,6 @@
|
||||
<Compile Include="PropertyEditors\ValueConverters\ColorPickerValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DatePickerValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DecimalValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DropdownListMultipleValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DropdownListMultipleWithKeysValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DropdownListValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DropdownListWithKeysValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\EmailAddressValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\GridValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\ImageCropperValueConverter.cs" />
|
||||
|
||||
Reference in New Issue
Block a user