Todo esto es asp.net c #.
Tengo una enumeración
public enum ControlSelectionType
{
NotApplicable = 1,
SingleSelectRadioButtons = 2,
SingleSelectDropDownList = 3,
MultiSelectCheckBox = 4,
MultiSelectListBox = 5
}
El valor numérico de esto se almacena en mi base de datos. Muestro este valor en una cuadrícula de datos.
<asp:boundcolumn datafield="ControlSelectionTypeId" headertext="Control Type"></asp:boundcolumn>
La ID no significa nada para un usuario, así que cambié la columna vinculada a una columna de plantilla con lo siguiente.
<asp:TemplateColumn>
<ItemTemplate>
<%# Enum.Parse(typeof(ControlSelectionType), DataBinder.Eval(Container.DataItem, "ControlSelectionTypeId").ToString()).ToString()%>
</ItemTemplate>
</asp:TemplateColumn>
Esto es mucho mejor ... Sin embargo, sería genial si hubiera una función simple que pudiera poner alrededor del Enum para dividirlo por el caso de Camel para que las palabras se ajusten bien en la cuadrícula de datos.
Nota: Soy plenamente consciente de que existen mejores formas de hacer todo esto. Esta pantalla se usa exclusivamente internamente y solo quiero un truco rápido para mostrarla un poco mejor.
Solía:
public static string SplitCamelCase(string input) { return System.Text.RegularExpressions.Regex.Replace(input, "([A-Z])", " $1", System.Text.RegularExpressions.RegexOptions.Compiled).Trim(); }
Tomado de http://weblogs.asp.net/jgalloway/archive/2005/09/27/426087.aspx
vb.net:
Public Shared Function SplitCamelCase(ByVal input As String) As String Return System.Text.RegularExpressions.Regex.Replace(input, "([A-Z])", " $1", System.Text.RegularExpressions.RegexOptions.Compiled).Trim() End Function
fuente
Esta expresión regular
(^[a-z]+|[A-Z]+(?![a-z])|[A-Z][a-z]+)
se puede utilizar para extraer todas las palabras del nombre camelCase o PascalCase. También funciona con abreviaturas en cualquier lugar dentro del nombre.MyHTTPServer
contendrá exactamente 3 partidos:My
,HTTP
,Server
myNewXMLFile
contendrá 4 partidos:my
,New
,XML
,File
Luego puede unirlos en una sola cadena usando
string.Join
.string name = "myNewUIControl"; string[] words = Regex.Matches(name, "(^[a-z]+|[A-Z]+(?![a-z])|[A-Z][a-z]+)") .OfType<Match>() .Select(m => m.Value) .ToArray(); string result = string.Join(" ", words);
fuente
@"(^\p{Ll}+|\p{Lu}+(?!\p{Ll})|\p{Lu}\p{Ll}+)"
también es importante tener en cuenta que esto no hará números en absoluto, aunque sean válidos en los identificadores.Si C # 3.0 es una opción, puede usar el siguiente resumen para hacer el trabajo:
Regex.Matches(YOUR_ENUM_VALUE_NAME, "[A-Z][a-z]+").OfType<Match>().Select(match => match.Value).Aggregate((acc, b) => acc + " " + b).TrimStart(' ');
fuente
La respuesta de Tillito no maneja bien las cadenas que ya contienen espacios, o acrónimos. Esto lo arregla:
public static string SplitCamelCase(string input) { return Regex.Replace(input, "(?<=[a-z])([A-Z])", " $1", RegexOptions.Compiled); }
fuente
Aquí hay un método de extensión que maneja números y múltiples caracteres en mayúscula con cordura, y también permite acrónimos específicos en mayúsculas en la cadena final:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Globalization; using System.Text.RegularExpressions; using System.Web.Configuration; namespace System { /// <summary> /// Extension methods for the string data type /// </summary> public static class ConventionBasedFormattingExtensions { /// <summary> /// Turn CamelCaseText into Camel Case Text. /// </summary> /// <param name="input"></param> /// <returns></returns> /// <remarks>Use AppSettings["SplitCamelCase_AllCapsWords"] to specify a comma-delimited list of words that should be ALL CAPS after split</remarks> /// <example> /// wordWordIDWord1WordWORDWord32Word2 /// Word Word ID Word 1 Word WORD Word 32 Word 2 /// /// wordWordIDWord1WordWORDWord32WordID2ID /// Word Word ID Word 1 Word WORD Word 32 Word ID 2 ID /// /// WordWordIDWord1WordWORDWord32Word2Aa /// Word Word ID Word 1 Word WORD Word 32 Word 2 Aa /// /// wordWordIDWord1WordWORDWord32Word2A /// Word Word ID Word 1 Word WORD Word 32 Word 2 A /// </example> public static string SplitCamelCase(this string input) { if (input == null) return null; if (string.IsNullOrWhiteSpace(input)) return ""; var separated = input; separated = SplitCamelCaseRegex.Replace(separated, @" $1").Trim(); //Set ALL CAPS words if (_SplitCamelCase_AllCapsWords.Any()) foreach (var word in _SplitCamelCase_AllCapsWords) separated = SplitCamelCase_AllCapsWords_Regexes[word].Replace(separated, word.ToUpper()); //Capitalize first letter var firstChar = separated.First(); //NullOrWhiteSpace handled earlier if (char.IsLower(firstChar)) separated = char.ToUpper(firstChar) + separated.Substring(1); return separated; } private static readonly Regex SplitCamelCaseRegex = new Regex(@" ( (?<=[a-z])[A-Z0-9] (?# lower-to-other boundaries ) | (?<=[0-9])[a-zA-Z] (?# number-to-other boundaries ) | (?<=[A-Z])[0-9] (?# cap-to-number boundaries; handles a specific issue with the next condition ) | (?<=[A-Z])[A-Z](?=[a-z]) (?# handles longer strings of caps like ID or CMS by splitting off the last capital ) )" , RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace ); private static readonly string[] _SplitCamelCase_AllCapsWords = (WebConfigurationManager.AppSettings["SplitCamelCase_AllCapsWords"] ?? "") .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(a => a.ToLowerInvariant().Trim()) .ToArray() ; private static Dictionary<string, Regex> _SplitCamelCase_AllCapsWords_Regexes; private static Dictionary<string, Regex> SplitCamelCase_AllCapsWords_Regexes { get { if (_SplitCamelCase_AllCapsWords_Regexes == null) { _SplitCamelCase_AllCapsWords_Regexes = new Dictionary<string,Regex>(); foreach(var word in _SplitCamelCase_AllCapsWords) _SplitCamelCase_AllCapsWords_Regexes.Add(word, new Regex(@"\b" + word + @"\b", RegexOptions.Compiled | RegexOptions.IgnoreCase)); } return _SplitCamelCase_AllCapsWords_Regexes; } } } }
fuente
Puede usar métodos de extensión de C #
public static string SpacesFromCamel(this string value) { if (value.Length > 0) { var result = new List<char>(); char[] array = value.ToCharArray(); foreach (var item in array) { if (char.IsUpper(item) && result.Count > 0) { result.Add(' '); } result.Add(item); } return new string(result.ToArray()); } return value; }
Entonces puedes usarlo como
var result = "TestString".SpacesFromCamel();
El resultado será
fuente
También tengo una
enum
que tuve que separar. En mi caso, este método resolvió el problema-string SeparateCamelCase(string str) { for (int i = 1; i < str.Length; i++) { if (char.IsUpper(str[i])) { str = str.Insert(i, " "); i++; } } return str; }
fuente
Usando LINQ:
var chars = ControlSelectionType.NotApplicable.ToString().SelectMany((x, i) => i > 0 && char.IsUpper(x) ? new char[] { ' ', x } : new char[] { x }); Console.WriteLine(new string(chars.ToArray()));
fuente
public enum ControlSelectionType { NotApplicable = 1, SingleSelectRadioButtons = 2, SingleSelectDropDownList = 3, MultiSelectCheckBox = 4, MultiSelectListBox = 5 } public class NameValue { public string Name { get; set; } public object Value { get; set; } } public static List<NameValue> EnumToList<T>(bool camelcase) { var array = (T[])(Enum.GetValues(typeof(T)).Cast<T>()); var array2 = Enum.GetNames(typeof(T)).ToArray<string>(); List<NameValue> lst = null; for (int i = 0; i < array.Length; i++) { if (lst == null) lst = new List<NameValue>(); string name = ""; if (camelcase) { name = array2[i].CamelCaseFriendly(); } else name = array2[i]; T value = array[i]; lst.Add(new NameValue { Name = name, Value = value }); } return lst; } public static string CamelCaseFriendly(this string pascalCaseString) { Regex r = new Regex("(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])"); return r.Replace(pascalCaseString, " ${x}"); } //In your form protected void Button1_Click1(object sender, EventArgs e) { DropDownList1.DataSource = GeneralClass.EnumToList<ControlSelectionType >(true); ; DropDownList1.DataTextField = "Name"; DropDownList1.DataValueField = "Value"; DropDownList1.DataBind(); }
fuente
La solución de Eoin Campbell funciona bien, excepto si tiene un servicio web.
Debería hacer lo siguiente ya que el atributo de descripción no es serializable.
[DataContract] public enum ControlSelectionType { [EnumMember(Value = "Not Applicable")] NotApplicable = 1, [EnumMember(Value = "Single Select Radio Buttons")] SingleSelectRadioButtons = 2, [EnumMember(Value = "Completely Different Display Text")] SingleSelectDropDownList = 3, } public static string GetDescriptionFromEnumValue(Enum value) { EnumMemberAttribute attribute = value.GetType() .GetField(value.ToString()) .GetCustomAttributes(typeof(EnumMemberAttribute), false) .SingleOrDefault() as EnumMemberAttribute; return attribute == null ? value.ToString() : attribute.Value; }
fuente
Y si no te apetece usar expresiones regulares, prueba esto:
public static string SeperateByCamelCase(this string text, char splitChar = ' ') { var output = new StringBuilder(); for (int i = 0; i < text.Length; i++) { var c = text[i]; //if not the first and the char is upper if (i > 0 && char.IsUpper(c)) { var wasLastLower = char.IsLower(text[i - 1]); if (i + 1 < text.Length) //is there a next { var isNextUpper = char.IsUpper(text[i + 1]); if (!isNextUpper) //if next is not upper (start of a word). { output.Append(splitChar); } else if (wasLastLower) //last was lower but i'm upper and my next is an upper (start of an achromin). 'abcdHTTP' 'abcd HTTP' { output.Append(splitChar); } } else { //last letter - if its upper and the last letter was lower 'abcd' to 'abcd A' if (wasLastLower) { output.Append(splitChar); } } } output.Append(c); } return output.ToString(); }
Pasa estas pruebas, no le gustan los números pero no los necesitaba.
[TestMethod()] public void ToCamelCaseTest() { var testData = new string[] { "AAACamel", "AAA", "SplitThisByCamel", "AnA", "doesnothing", "a", "A", "aasdasdAAA" }; var expectedData = new string[] { "AAA Camel", "AAA", "Split This By Camel", "An A", "doesnothing", "a", "A", "aasdasd AAA" }; for (int i = 0; i < testData.Length; i++) { var actual = testData[i].SeperateByCamelCase(); var expected = expectedData[i]; Assert.AreEqual(actual, expected); } }
fuente
#JustSayNoToRegex
Toma un identificador de C #, con uderscores y números, y lo convierte en una cadena separada por espacios.
public static class StringExtensions { public static string SplitOnCase(this string identifier) { if (identifier == null || identifier.Length == 0) return string.Empty; var sb = new StringBuilder(); if (identifier.Length == 1) sb.Append(char.ToUpperInvariant(identifier[0])); else if (identifier.Length == 2) sb.Append(char.ToUpperInvariant(identifier[0])).Append(identifier[1]); else { if (identifier[0] != '_') sb.Append(char.ToUpperInvariant(identifier[0])); for (int i = 1; i < identifier.Length; i++) { var current = identifier[i]; var previous = identifier[i - 1]; if (current == '_' && previous == '_') continue; else if (current == '_') { sb.Append(' '); } else if (char.IsLetter(current) && previous == '_') { sb.Append(char.ToUpperInvariant(current)); } else if (char.IsDigit(current) && char.IsLetter(previous)) { sb.Append(' ').Append(current); } else if (char.IsLetter(current) && char.IsDigit(previous)) { sb.Append(' ').Append(char.ToUpperInvariant(current)); } else if (char.IsUpper(current) && char.IsLower(previous) && (i < identifier.Length - 1 && char.IsUpper(identifier[i + 1]) || i == identifier.Length - 1)) { sb.Append(' ').Append(current); } else if (char.IsUpper(current) && i < identifier.Length - 1 && char.IsLower(identifier[i + 1])) { sb.Append(' ').Append(current); } else { sb.Append(current); } } } return sb.ToString(); } }
Pruebas:
[TestFixture] static class HelpersTests { [Test] public static void Basic() { Assert.AreEqual("Foo", "foo".SplitOnCase()); Assert.AreEqual("Foo", "_foo".SplitOnCase()); Assert.AreEqual("Foo", "__foo".SplitOnCase()); Assert.AreEqual("Foo", "___foo".SplitOnCase()); Assert.AreEqual("Foo 2", "foo2".SplitOnCase()); Assert.AreEqual("Foo 23", "foo23".SplitOnCase()); Assert.AreEqual("Foo 23 A", "foo23A".SplitOnCase()); Assert.AreEqual("Foo 23 Ab", "foo23Ab".SplitOnCase()); Assert.AreEqual("Foo 23 Ab", "foo23_ab".SplitOnCase()); Assert.AreEqual("Foo 23 Ab", "foo23___ab".SplitOnCase()); Assert.AreEqual("Foo 23", "foo__23".SplitOnCase()); Assert.AreEqual("Foo Bar", "Foo_bar".SplitOnCase()); Assert.AreEqual("Foo Bar", "Foo____bar".SplitOnCase()); Assert.AreEqual("AAA", "AAA".SplitOnCase()); Assert.AreEqual("Foo A Aa", "fooAAa".SplitOnCase()); Assert.AreEqual("Foo AAA", "fooAAA".SplitOnCase()); Assert.AreEqual("Foo Bar", "FooBar".SplitOnCase()); Assert.AreEqual("Mn M", "MnM".SplitOnCase()); Assert.AreEqual("AS", "aS".SplitOnCase()); Assert.AreEqual("As", "as".SplitOnCase()); Assert.AreEqual("A", "a".SplitOnCase()); Assert.AreEqual("_", "_".SplitOnCase()); } }
fuente
Versión simple similar a algunas de las anteriores, pero con lógica para no insertar automáticamente el separador (que por defecto es un espacio, pero puede ser cualquier carácter) si ya hay uno en la posición actual.
Utiliza
StringBuilder
cadenas en lugar de "mutantes".public static string SeparateCamelCase(this string value, char separator = ' ') { var sb = new StringBuilder(); var lastChar = separator; foreach (var currentChar in value) { if (char.IsUpper(currentChar) && lastChar != separator) sb.Append(separator); sb.Append(currentChar); lastChar = currentChar; } return sb.ToString(); }
Ejemplo:
fuente
Prueba esto:
using System; using System.Linq; using System.Collections.Generic; public class Program { public static void Main() { Console .WriteLine( SeparateByCamelCase("TestString") == "Test String" // True ); } public static string SeparateByCamelCase(string str) { return String.Join(" ", SplitByCamelCase(str)); } public static IEnumerable<string> SplitByCamelCase(string str) { if (str.Length == 0) return new List<string>(); return new List<string> { Head(str) } .Concat( SplitByCamelCase( Tail(str) ) ); } public static string Head(string str) { return new String( str .Take(1) .Concat( str .Skip(1) .TakeWhile(IsLower) ) .ToArray() ); } public static string Tail(string str) { return new String( str .Skip( Head(str).Length ) .ToArray() ); } public static bool IsLower(char ch) { return ch >= 'a' && ch <= 'z'; } }
Ver muestra en línea
fuente