tags:

views:

244

answers:

3

I have a property of datattype enum : like

public BreakLevel Level
{
    get { return level; }
    set { level = value; }
}

And enum defined :

  public enum BreakLevel
    {
        Warning, Fatal
    }

I want bind the neum property to the visibility of my border , somewhat like this:

Visibility="{Binding BreakLevel.Fatal}" so is it possible?

<Border CornerRadius="4" BorderThickness="1"  BorderBrush="#DAE0E5"  
Visibility="{Binding DataContext.IsError, Converter={StaticResource BoolToVisibilityConverter}, RelativeSource={RelativeSource TemplatedParent}}" >
+3  A: 

I think you can just create a BreakLevelToVisibilityConverter and bind just like the example you provided.

I'm assuming that the DataContext of your border is set to an instance of a class that has a property of type 'BreakLevel' (we'll call this property 'BreakLvlProperty').

The code below will then show the border if the value of BreakLvlProperty is BreakLevel.Fatal

Converter:

public class BreakLevelToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if ((BreakLevel)value == BreakLevel.Fatal)
            return Visibility.Visible;
        else
            return Visibility.Hidden;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

XAML:

<TopLevelWindowOrControl.Resources>
    <local:BreakLevelToVisibilityConverter x:Key="BreakLevelToVisibilityConverter" />
</TopLevelWindowOrControl.Resources>

<Border Visibility="{Binding Path=BreakLvlProperty, Converter={StaticResource BreakLevelToVisibilityConverter}" />
Scott
Hey scott thanks u r example helped me to solve mine problem :)
Malcolm
+1  A: 

Scott has a good answer to the actual question, however its always a good idea to ask yourself "How might I need code like this in the future? How can I avoid creating yet another class and instead re-use what I have already got?".

Here is a more general variation of Scott's solution:-

public class EnumToVisibilityConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
        if (Enum.GetName(value.GetType(), value).Equals(parameter)) 
            return Visibility.Visible; 
        else 
            return Visibility.Hidden; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
        return null; 
    } 
} 

Xaml:-

<TopLevelWindowOrControl.Resources>   
    <local:EnumToVisibilityConverter x:Key="EnumToVisibilityConverter" />   
</TopLevelWindowOrControl.Resources>   

<Border Visibility="{Binding Path=BreakLvlProperty, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter=Fatal" />

In this approach we can converter any enum to a Visibility value by using the ConverterParameter to specify the enum value (in string form) that constitute the "Visible" state.

Its tempting to take this further to allow more than one enum value to be equated to "Visible". However currently the code isn't much more complicated than Scott's more specific implementation. Hence this enhancement should be left until needed.

AnthonyWJones
Interesting you mentioned this Anthony! I was just refactoring some of my own code after I wrote this response and did something extremely similar to your answer (I bind visibility to a class instead of an enum). Instead of setting the ConverterParameter to a string representing the enum, I set it to the actual type: {x:Type local:MyClassType}. My converter: if ((parameter as Type).IsInstanceOfType(value)) return Visibility.Visible else return Visibility.Hidden. Do you know if there is a good way to enforce usage of the ConverterParameter at design time?
Scott
@Scott: First of all Silverlight does support `x:Type` so that kinda scuppers things to start with. There isn't anyway to "enforce" usage of any property in Silverlight at design time, I can't even imagine how such "enforcement" might operate. The closest you would get is a compile time error. Unfortunately Silverlight is notorious for its Runtime errors when the Xaml is clearly in error, it does cause many devs to ask "Why isn't this picked up at compile time?".
AnthonyWJones
@Anthony: Thanks for the response! (I didn't even realize this was for Silverlight... lol... I'm a WPF guy). I didn't think there was a way to enforce the parameter... but just wanted to check if you knew of any. Right now I am checking if it's null and if it ('is Type') and if not, I throw an argument exception in my converter. Not sure if that's good practice or not, but I figure it'll help find the error sooner than later if it gets used by any future developers on my code.Thanks again!
Scott
@Anthony u r answer is similar to what i did.I took this approach only.
Malcolm
@Anthony i have posted my answer...I am also checking if the for the null value too :)
Malcolm
I just marked the scott answer right because i thought to start with it was a good answer and the rest we can modify how i or any developer loking for the enum thing.
Malcolm
A: 
public class EnumToVisibilityConvertor : IValueConverter
{
    private bool chk;
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if ((value != null) && (value is BreakLevel) && (targetType == typeof(Visibility)))
        {
          chk =   ((((BreakLevel) value) == (BreakLevel) Enum.Parse(typeof (BreakLevel), parameter.ToString(), true)));
          return (chk==true) ? Visibility.Visible : Visibility.Collapsed;
        }

        throw new InvalidOperationException("Invalid converter usage.");
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;

    }
}





      <Border CornerRadius="4" BorderThickness="1"  BorderBrush="#DAE0E5"  
Visibility="{Binding Path=Level, Converter={StaticResource enumToVisibilityConvertor},ConverterParameter=Fatal}" >
Malcolm
Certainly its more belts and braces than my approach. However you really don't need the `chk` as a field or even as a variable. You don't need to compare a boolean value with ==true. Loose `chk` and the ternary operate ? : and use a simple if..else instead.
AnthonyWJones