简体   繁体   中英

How to pass multiple converter parameter in generic Enum to Boolean Converter

I have been through this How to bind RadioButtons to an enum?

and accepted answer to this question contains use of generic Enum to Boolean converter.

my problem is that I am having two radio buttons in View and an enum

 public Enum LinkType
   {
       A,
       B,
       C,
       D,
       E,
       F
    }

In ViewModel I have a property Called

public LinkType MyLinktype
{
  get;set;
}

my first radio button can be true if property of enum in ViewModel is having value among A,C,E and second radio button can be true if property of enum in ViewModel is having value among. B,D,F

So, How can I pass multiple values in the converter parameter in generic EnumTo Boolean Converter which is as following

 public class EnumBooleanConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string parameterString = parameter as string;
            if (parameterString == null)
                return DependencyProperty.UnsetValue;

            if (Enum.IsDefined(value.GetType(), value) == false)
                return DependencyProperty.UnsetValue;

            object parameterValue = Enum.Parse(value.GetType(), parameterString);

            return parameterValue.Equals(value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string parameterString = parameter as string;
            if (parameterString == null)
                return DependencyProperty.UnsetValue;

            return Enum.Parse(targetType, parameterString);
        }

So what changes I have to make in converter if I want something like this in the XAML

<RadioButton IsChecked="{Binding Path=MyLinktype, Converter={StaticResource enumBooleanConverter}, ConverterParameter=A,C,F}">Odd LinkType</RadioButton>

 <RadioButton IsChecked="{Binding Path=Mylinktype, Converter={StaticResource enumBooleanConverter}, ConverterParameter=B,D,E}">Even Link Type</RadioButton>

You can define an array in xaml:

        <x:Array Type="LinkType" x:Key="ar">
            <LinkType>A</LinkType>
            <LinkType>B</LinkType>
        </x:Array>

And then pass it as parameter

<RadioButton IsChecked="{Binding Path=MyLinktype, Converter={StaticResource enumBooleanConverter}, ConverterParameter={StaticResource ar}}">Odd LinkType</RadioButton>

You'll have to fix your converter tho, in order to properly handle array as converter parameter.

Firstly, I think "Flags" attribute is the key to resolve the problem:

[Flags]
public enum LinkType
{
    A=1,
    B=2,
    C=4,
    D=8,
    E=16
}

And then, I implement the converter like this:

public class LinkTypeToBoolCvt : IValueConverter
{
    #region | Members of IValueConverter |

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // please refer to the implementation of "CallBack" method
        throw new NotImplementedException();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null || parameter == null) return DependencyProperty.UnsetValue;

        var param= parameter.ToString();
        int result;
        if (int.TryParse(param,out result))
        {
            // ex: if the parameter is 11, the result will be "A|B|D"
            return result;
        }
        else
        {
            // ex: if the parameter is "A|E", the result will be 17
            var enums = param.Split(new []{"|"}, StringSplitOptions.RemoveEmptyEntries);

            LinkType lt = 0;
            LinkType ltTemp = 0;

            foreach (var item in enums)
            {
                if (Enum.TryParse<LinkType>(item, out ltTemp)) lt |= ltTemp;
            }

            if (lt == 0) return DependencyProperty.UnsetValue;
            else return lt;
        }
    } 

    #endregion
}

And, in Xaml you can use it like this:

<RadioButton IsChecked="{Binding .MyLinkType,Converter={StaticResource LinkTypeToBoolCvt},ConverterParameter=11}" />

Also like this:

<RadioButton IsChecked="{Binding .MyLinkType,Converter={StaticResource LinkTypeToBoolCvt},ConverterParameter=A|B|D}" />

if you dont use "Flags" attribute, you cannot transfer the result like "A|B|D" back to your model.

Finally, I should apologize for my poor english. ^-^

You can use following enum to boolean converter

 [ValueConversion(typeof(Enum), typeof(bool))]
 public class EnumToBooleanConverter : IValueConverter
 {
   public object Convert(object value,
                      Type targetType,
                      object parameter,
                      CultureInfo culture)
       {
         if (
             (value == null) 
             || 
             (!(value is Enum))
             ||
             (parameter == null)
             )
                {
                   return false;
                }

  foreach (Enum paramValue in ParseObjectToEnum(value.GetType(),
                                                parameter))
  {
    if (value.Equals(paramValue))
    {
      return true;
    } 
  }

  return false;
}



public object ConvertBack(object value,
                          Type targetType,
                          object parameter,
                          CultureInfo culture)
{
  object result = Binding.DoNothing;

  if ((bool)value)
  {
    Enum[] parsedValues = ParseObjectToEnum(targetType,
                                            parameter);
    if (parsedValues.Length > 0)
    {
      result = parsedValues[0];
    } 
  }
  return result;
} 


private static Enum[] ParseObjectToEnum(Type enumType,
                                        object value)
{
  var enumValue = value as Enum;
  if (enumValue != null)
  {
    return new[] { enumValue };
  }

  var str = value as string;
  if (string.IsNullOrEmpty(str))
  {
    throw new ArgumentException("parameter");
  }

  string[] strArray = str.Split(new[] { ';', ',' },
                                StringSplitOptions.RemoveEmptyEntries);
  var enumArray = new Enum[strArray.Length];
  for (int i = 0;
       i < strArray.Length;
       i++)
  {
    enumArray[i] = (Enum)Enum.Parse(enumType,
                                    strArray[i],
                                    true);
  }

  return enumArray;
} 

}

and in xaml you can use like

<RadioButton IsChecked="{Binding Path=MyLinktype, Converter={StaticResource enumBooleanConverter}, ConverterParameter=A;C;F}">Odd LinkType</RadioButton>

where enumBooleanConverter is the above converter

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM