0

For different user interfaces I want to show an image depending on a state of a ViewModel object.

For example:

I have a database connection, if connected, I want to show a green database image, if not connected I want to display a red database image.

In the ViewModel there is a bool that represents the state.

Possibilities are:

  • Having two images in the view (with a converter InverseBooleanToVisibilityConverter for the red image), which are at the same place, actually just showing one of them.

  • Binding for Image source (but I do not want to set this in my ViewModel)

  • Some sort of selector?

This state depending image can be more often of use, e.g. in a TreeView as ItemImage.

Is there a more clever way to accomplish that?

Mare Infinitus
  • 8,024
  • 8
  • 64
  • 113

3 Answers3

3

You can also do it with solely with data triggers. Here's a sample from one of my projects for a button that changes it's image depending on whether or not the form is in an Edit mode or not:

<Button x:Name="EditOrSaveJob"
                    Width="32"
                    Height="32"
                    Margin="10,0,0,0"
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Stretch">
                <Image>
                    <Image.Style>
                        <Style TargetType="Image">
                            <Setter Property="Source" Value="/AAAA;component/Resources/Images/edit.png" />
                            <Setter Property="ToolTip" Value="Edit Order" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsEditing}" Value="True">
                                    <Setter Property="Source" Value="/AAAA;component/Resources/Images/32_save.png" />
                                    <Setter Property="ToolTip" Value="Save Order" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Image.Style>
                </Image>
</Button>
Jason Massey
  • 1,088
  • 10
  • 18
1

The solution would be using converter (class that implements IValueConverter):

class ImageStateConverter : IValueConverter
{
    public Object Convert(  Object value, Type targetType, Object parameter,    CultureInfo culture)    
    {
        bool state = (bool) value;
        return state ? "img1.png" : "img2.png";
    }
}

Then in your XAML write binding like this:

<Image Source="{Binding Path=State, Converter={StaticResource myConverter}}" />

Object myConverter is declared somewhere in Resources section.

  • The reason I don't like this approach is that it isn't reusable and you end up with a new type every time you need to toggle a new image. You could make it a little better by using virtual/abstract properties instead of hard coded string constants. – Yaur May 14 '13 at 20:40
  • Thought about some converter like this one, but I want my image file references in the XAML, nowhere else. Thank you for your answer. – Mare Infinitus May 14 '13 at 20:45
  • i wanted to merely show how wpf converters work, of course in real code you should expose properties for every image file reference – Jakub Jarzabek May 14 '13 at 21:00
1

I use a valueconverter like so:

public class BoolToImageConverter: DependencyObject, IValueConverter
{

    public BitmapImage TrueImage
    {
        get { return (BitmapImage)GetValue(TrueImageProperty); }
        set { SetValue(TrueImageProperty, value); }
    }
    public static DependencyProperty TrueImageProperty = DependencyProperty.Register("TrueImage", typeof(BitmapImage), typeof(BoolToImageConverter), null);


    public BitmapImage FalseImage
    {
        get { return (BitmapImage)GetValue(FalseImageProperty); }
        set { SetValue(FalseImageProperty, value); }
    }
    public static DependencyProperty FalseImageProperty = DependencyProperty.Register("FalseImage", typeof(BitmapImage), typeof(BoolToImageConverter), null);

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (bool)value ? TrueImage : FalseImage;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var img = (BitmapImage)value;
        return img.UriSource.AbsoluteUri == TrueImage.UriSource.AbsoluteUri;
    }

}

and in XAML

<my:BoolToImageConverter x:Key="converterName" FalseImage="{StaticResource falseImage}" TrueImage="{StaticResource trueImage}"/>
Yaur
  • 7,333
  • 1
  • 25
  • 36