You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
5.6 KiB
143 lines
5.6 KiB
using System;
|
|
using System.ComponentModel;
|
|
using System.Globalization;
|
|
using System.Reflection;
|
|
using System.Windows.Data;
|
|
using System.Collections.Generic;
|
|
using System.Windows.Controls;
|
|
|
|
namespace MultiTerm.Wpf.ValueConverters;
|
|
|
|
/// <summary>
|
|
/// Converts an Enum (using its Description Attribute) to a Menu Item.
|
|
/// The Menu Item has the Description assigned to its Header.
|
|
/// If the Enum has no Description, it will convert the Enum Value to string and use this.
|
|
/// </summary>
|
|
[ValueConversion(typeof(Enum), typeof(MenuItem))]
|
|
public class EnumDescriptionToMenuItemConverter : IValueConverter
|
|
{
|
|
/// <summary>
|
|
/// Gets the description of an Enum value.
|
|
/// If there is no Description set, the Enum Value will be converted to string.
|
|
/// </summary>
|
|
/// <param name="enumObject">Enum Object to get Description of.</param>
|
|
/// <returns>String with Content of DescriptionAttribute of Enum object.</returns>
|
|
private static string GetEnumDescription(Enum enumObject)
|
|
{
|
|
// guard argument null
|
|
if(enumObject == null) { throw new ArgumentNullException(nameof(enumObject)); }
|
|
|
|
// get field info from enum type
|
|
FieldInfo? fieldInfo = enumObject.GetType().GetField(enumObject.ToString());
|
|
// return string of enum value if there is no field info
|
|
if (fieldInfo == null)
|
|
{
|
|
return enumObject.ToString();
|
|
}
|
|
|
|
// get description attribute and return if it is present
|
|
DescriptionAttribute? descAttrib = (DescriptionAttribute?)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute), true);
|
|
if (descAttrib != null)
|
|
{
|
|
return descAttrib.Description;
|
|
}
|
|
|
|
// if no description attribute was found => return string of enum value
|
|
return enumObject.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets all Description Attributes of a Enum type.
|
|
/// Descriptions must be unique!
|
|
/// </summary>
|
|
/// <param name="enumObject">An object of the Enum. Will be searched for other Descriptions</param>
|
|
/// <returns>Key Value Pair of Description and respective Enum Value</returns>
|
|
private static Dictionary<string, Enum> GetAllEnumDescriptions(Enum enumObject)
|
|
{
|
|
// guard argument null
|
|
if (enumObject == null) { throw new ArgumentNullException(nameof(enumObject)); }
|
|
|
|
Dictionary<string, Enum> descriptionsToEnumValues = new();
|
|
|
|
// get members of enum type
|
|
var members = enumObject.GetType().GetMembers();
|
|
foreach (var member in members)
|
|
{
|
|
// get description attributes of all members
|
|
DescriptionAttribute? descAttrib = (DescriptionAttribute?)member.GetCustomAttribute(typeof(DescriptionAttribute), true);
|
|
if(descAttrib != null)
|
|
{
|
|
// if a description exists, add the description and the enum value to the dictionary
|
|
descriptionsToEnumValues.Add(descAttrib.Description, (Enum)Enum.Parse(enumObject.GetType(), member.Name));
|
|
}
|
|
}
|
|
|
|
return descriptionsToEnumValues;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert from Data Source to Dependency Object type.
|
|
/// Here: Enum type to MenuItem.
|
|
/// </summary>
|
|
/// <param name="value">value to convert</param>
|
|
/// <param name="targetType">type to convert to</param>
|
|
/// <param name="parameter">no parameter required</param>
|
|
/// <param name="culture">most likely CultureInfo.CurrentCulture</param>
|
|
/// <returns>New MenuItem with Enum description in Header property</returns>
|
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
Enum enumValue = (Enum)value;
|
|
string description = GetEnumDescription(enumValue);
|
|
MenuItem newMenuItem = new()
|
|
{
|
|
Header = description
|
|
};
|
|
return newMenuItem;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert from Dependency Object type to Data Source type.
|
|
/// Here: MenuItem to Enum type.
|
|
/// </summary>
|
|
/// <param name="value">value to convert</param>
|
|
/// <param name="targetType">type to convert to</param>
|
|
/// <param name="parameter">no parameter required</param>
|
|
/// <param name="culture">most likely CultureInfo.CurrentCulture</param>
|
|
/// <returns>Enum value of the MenuItem that was converted</returns>
|
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
Enum? enumObj;
|
|
|
|
// guard argument null
|
|
if (targetType == null) { throw new ArgumentNullException(nameof(targetType)); }
|
|
if (value == null) { throw new ArgumentNullException(nameof(value)); }
|
|
|
|
// extract menu item and guard null
|
|
if (value is not MenuItem menuObject)
|
|
{
|
|
throw new Exception($"Cannot convert value that is not of type {nameof(MenuItem)} with {nameof(EnumDescriptionToMenuItemConverter)}");
|
|
}
|
|
|
|
// generate instance of enum using target type
|
|
enumObj = Activator.CreateInstance(targetType) as Enum;
|
|
if (enumObj == null)
|
|
{
|
|
throw new Exception($"Could not instanciate Enum of targetType {targetType}.");
|
|
}
|
|
|
|
// get all enum descriptions and iterate
|
|
var descriptionToEnumValue = GetAllEnumDescriptions(enumObj);
|
|
foreach (var kvp in descriptionToEnumValue)
|
|
{
|
|
// compare key (enum description) to menu header
|
|
if(String.Compare(kvp.Key, menuObject.Header.ToString(), true) == 0)
|
|
{
|
|
// if correct description is found, return according enum value
|
|
return kvp.Value;
|
|
}
|
|
}
|
|
|
|
// if nothing worked => return value
|
|
return value;
|
|
}
|
|
}
|
|
|