using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
namespace XYY.Windows.SAAS.WpfExtention.Converters
{
public class CommonCoverter : IValueConverter
{
private static PropertyInfo[] _brushes;
private static readonly Dictionary<string, Dictionary<string, string>> _globalParam2strKV = new Dictionary<string, Dictionary<string, string>>();
/// 转换器参数语法: key1,value1 key2,value2 ... [other,defaultValue] [object>bool] [contains(:)] [key1,RS_red key2,#33f0f0f0 other,blue]
/// -----------1---------------- -------2------------ ------3------ ---4--------- ------------5------------------------
/// 1:必填,为键值对,用空格分隔,不限键值对个数
/// 2:选填,如果你想要1转成true,其他转成false: 1,true other,false ;也可以1和2转成true,其他转成flase: 1,true 2,true other,false
/// 3:选填,像DataTrigger的value是object类型的, 如果用了此转换器需要手动指定转换类型. 例如 object>visibility 1,visible 2,hidden
/// 4:选填,只有在string->bool 时才使用,判断字符串中是否包含 例如 contains(某字符串),使用了4,1可以不填
/// 5:选填,只有其他->brush时才能使用,支持从app资源获取、#加ARGB/RGB、brush枚举值名称
/// 6:datetime->string 不需要写parameter 会自动把datetime的默认值转成空字符串
/// 7:当value是枚举值时,会尝试直接返回description attribute的值,如果没有attribute照常返回
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var vtype = value.GetType();
const string other = "other";
#region enum
//如果是枚举值,description的attribute优先转换
if (parameter == null && vtype.IsEnum)
{
var memInfo = vtype.GetMember(value.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);
if (attributes?.Count() > 0)
{
return (attributes[0] as DescriptionAttribute).Description;
}
else
{
return value;
}
}
#endregion
#region 参数转dictionary
string objectType = null;
var paramStr = parameter as string ?? string.Empty;
if (!((value is DateTime) && targetType == typeof(string)))
{
if (targetType == typeof(object) && Regex.IsMatch(paramStr, @"object>(w+)"))
objectType = Regex.Match(paramStr, @"object>(w+)").Groups[1].Value;
if ((targetType == typeof(bool) || targetType == typeof(bool?) || objectType == "bool") && value is string v_str)
{
var r = v_str.Contains(Regex.Match(paramStr, @"((.*))").Groups[1].Value);
return r;
}
if (!_globalParam2strKV.ContainsKey(paramStr))
{
_globalParam2strKV.Add(paramStr, new Dictionary<string, string>());
foreach (Match m in Regex.Matches(paramStr, @"(w+)?\,[^s]+"))
{
var p_key = Regex.Match(m.Value, @"^(w+)?").Value.ToLower();
var p_value = Regex.Match(m.Value, @"(?<=\,)[^s]+$").Value;
_globalParam2strKV[paramStr].Add(p_key, p_value);
}
}
}
#endregion
var valueStrLower = value?.ToString()?.ToLower() ?? string.Empty;
//brush
if (targetType == typeof(Brush) || targetType == typeof(SolidColorBrush) || objectType == "brush")
{
if (_globalParam2strKV[paramStr].ContainsKey(valueStrLower))
{
var temp = _globalParam2strKV[paramStr][valueStrLower];
if (Regex.IsMatch(temp, @"^RS_"))
{
return Application.Current.TryFindResource(Regex.Replace(temp, @"^RS_", m => string.Empty));
}
else if (Regex.IsMatch(temp, @"^#"))
{
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(temp));
}
else
{
if (_brushes?.Any() != true)
{
_brushes = typeof(Brushes).GetProperties(BindingFlags.Public | BindingFlags.Static);
}
return _brushes.FirstOrDefault(t => t.Name.ToLower() == temp.ToLower())?.GetValue(null, null);
}
}
else
{
return _globalParam2strKV[paramStr].ContainsKey(other) ? _globalParam2strKV[paramStr][other] : (object)Brushes.Transparent;
}
}
// to visibility
if (targetType == typeof(Visibility) || targetType == typeof(Visibility?) || objectType == "visibility")
{
if (_globalParam2strKV[paramStr].ContainsKey(valueStrLower))
{
var temp = _globalParam2strKV[paramStr][valueStrLower].ToLower();
Visibility visibilityResult = Visibility.Collapsed;
switch (temp)
{
case "visible":
visibilityResult = Visibility.Visible; break;
case "hidden":
visibilityResult = Visibility.Hidden; break;
case "collapsed":
visibilityResult = Visibility.Collapsed; break;
default:
break;
}
return visibilityResult;
}
else
{
return _globalParam2strKV[paramStr].ContainsKey(other) ? _globalParam2strKV[paramStr][other] : (object)Visibility.Collapsed;
}
}
// to int
if (targetType == typeof(int) || targetType == typeof(int?) || objectType == "int")
{
if (_globalParam2strKV[paramStr].ContainsKey(valueStrLower))
{
var temp = _globalParam2strKV[paramStr][valueStrLower].ToLower();
return int.Parse(temp);
}
else
{
return _globalParam2strKV[paramStr].ContainsKey(other) ? _globalParam2strKV[paramStr][other] : (object)0;
}
}
// to bool
if (targetType == typeof(bool?) || targetType == typeof(bool) || objectType == "bool")
{
if (_globalParam2strKV[paramStr].ContainsKey(valueStrLower))
{
var temp = _globalParam2strKV[paramStr][valueStrLower].ToLower();
return bool.Parse(temp);
}
else
{
return _globalParam2strKV[paramStr].ContainsKey(other) ? _globalParam2strKV[paramStr][other] : (object)false;
}
}
// to string
if (targetType == typeof(string) || objectType == "string")
{
if (_globalParam2strKV[paramStr].ContainsKey(valueStrLower))
{
return _globalParam2strKV[paramStr][valueStrLower];
}
else
{
return _globalParam2strKV[paramStr].ContainsKey(other) ? _globalParam2strKV[paramStr][other] : null;
}
}
//datetime
if (targetType == typeof(string) && (value is DateTime dt))
{
if (dt == DateTime.MinValue)
{
return string.Empty;
}
else
{
return _globalParam2strKV[paramStr].ContainsKey(other) ? _globalParam2strKV[paramStr][other] : (object)dt;
}
}
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
}