I would like to change my image source from:
<Image Source="{svg:SvgImage image.svg}"/>
To something that use binding on an enum property instead:
XAML:
<Resources>
<local:MyConverter x:Key="MyConverter" />
</Resources>
<Image Source="{svg:SvgImage Binding MyEnumProperty, Converter={StaticResource MyConverter}}" />
Code behind:
public enum MyEnum
{
Value1,
Value2
}
public class MyConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var myValue = (MyEnum)(value);
switch (myValue)
{
case MyEnum.Value1:
return "image1.svg";
case MyEnum.Value2:
return "image2.svg";
default:
throw new NotImplementedException();
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
This doesn't work and I suspect that is has something to do with the svg:SvgImage and Binding MyEnumProperty being combined in the same statement.
I get the following errors:
The member "Converter" is not recognized or is not accessible.
And
The property 'Converter' was not found in type 'SvgImageExtension'.
Question:
What is the correct way to do this?
The expression
{svg:SvgImage Binding MyEnumProperty ...}
is not valid XAML, and because SvgImage is a markup extension, you can't bind its properties.
You may however use DataTriggers in an Image Style instead of a Binding with a Converter:
<Image>
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding MyEnumProperty}" Value="Value1">
<Setter Property="Source" Value="{svg:SvgImage image1.svg}"/>
</DataTrigger>
<DataTrigger Binding="{Binding MyEnumProperty}" Value="Value2">
<Setter Property="Source" Value="{svg:SvgImage image2.svg}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Related
I have a DataGridTemplateColumn, whose Width I'd like to change based on the related boolean property.
Now I'm using a converter as shown in the code below in order to achieve my purpose.
<DataGridTemplateColumn Width="{Binding IsFull, Converter={StaticResource BooleanToColumnWidthConverter}}">
</DataGridTemplateColumn>
public class BooleanToColumnWidthConverter : IValueConverter
{
private static readonly DataGridLength NORMAL_WIDTH = new DataGridLength(10, DataGridLengthUnitType.Star);
private static readonly DataGridLength NARROWED_WIDTH = new DataGridLength(3, DataGridLengthUnitType.Star);
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is bool)) { return DependencyProperty.UnsetValue; }
var isFull = (bool) value;
return isFull ? FULL_WIDTH : NARROWED_WIDTH;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
Is it possible to get the same result without using a converter, for example by defining something like a style or a template as shown in the following?
<!-- This does not compile. -->
<Style TargetType="DataGridTemplateColumn">
<Setter Property="Width" Value="10*"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsFull}" Value="False">
<Setter Property="Width" Value="3*"/>
</DataTrigger>
</Style.Triggers>
</Style>
How can change the fill color of an object I'm being to in my mvvm setup using xaml in wpf. I want to change the fill color to red when the attribute being bound to is set to True.
The attribute is called IsRound.
I'll post code if necessary. I'm not on a pc at the moment.
UPDATED
Could someone show an example of how to do this using style triggers?
And set the value based on the bind property bool?
First of all you don't need any Binding for what you are trying to do. DataTrigger is enough. In the example below IsCyan is a boolean property of ViewModel. But Background of TextBlock is not bound at all.
<TextBlock Text="Inside content">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsCyan}" Value="True">
<Setter Property="Background" Value="DarkCyan"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsCyan}" Value="False">
<Setter Property="Background" Value="DarkGoldenrod"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
But if at all you need Binding, solution by the user benPearce to use Converter is the way to go.
You need to use an IValueConverter on the binding.
BackgroundColor="{Binding Path=IsRound, Converter={StaticResource BoolToFillColorConverter}}"
public class BoolToFillColorConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool b;
if (bool.TryParse(value, out b))
{
if (b) return Red
else return Blue;
}
else
{
return SomeDefaultColour;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
I would like to permit the user to change the Window ResizeMode property, set by default in my case to ResizeMode="CanMinimize". How could it be switched to ResizeMode="CanResize"?
I think it could be done by creating a Boolean (or a CheckBox.IsChecked property) bound to ResizeMode with a converter, but I'm not sure if that's the way. Even if it was the right option I don't know how to create a converter that converts "True" to "CanResize" and "False" to "CanMinimize".
I prefer a Trigger solution
<Window>
<CheckBox Name="checkbox" Content="CanResize" />
<Window.Style>
<Style TargetType="Window">
<Setter Property="ResizeMode" Value="CanMinimize" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=checkbox}" Value="True">
<Setter Property="ResizeMode" Value="CanResize" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Style>
</Window>
Creating a converter is pretty simple right.
Have something like:
using System.Globalization;
using System.Windows;
using System.Windows.Data;
public class ResizeModeConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
return (bool)value ? ResizeMode.CanResize : ResizeMode.CanMinimize;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
and add this converter to your App.xaml Resources(Converter should be in a scope available to your Window)
<Application.Resources>
<local:ResizeModeConverter x:Key="ResizeModeConverter" />
</Application.Resources>
Now in your Window
<Window ... ResizeMode="{Binding SomeProperty, Converter={StaticResource ResizeModeConverter}}">
Now when SomeProperty is set to true or false you get your required behavior. You can set the property in your VM at startup after reading your local setting's or modify it at runtime and everything should be fine.
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?
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>
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}"/>
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.
I wrote an application in WPF that has a button and slider. I would like to create a trigger for the button, which would set the button's 'IsEnable' property to false when the slider value is greater than another value.
Right now I have:
<Style x:Key="zoomOutButton" TargetType="Button" BasedOn="{StaticResource ResourceKey=buttonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentAltitude}" Value="24000">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
But I would like to set isEnable not when the value of CurrentAltitude equal 24000, but when it is equal or greater than 24000.
Any ideas?
You can achieve this using a converter:
public class IsEqualOrGreaterThanConverter : IValueConverter {
public static readonly IValueConverter Instance = new IsEqualOrGreaterThanConverter();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
int intValue = (int) value;
int compareToValue = (int) parameter;
return intValue >= compareToValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
Then your trigger will look like this:
<Style x:Key="zoomOutButton" TargetType="Button" BasedOn="{StaticResource ResourceKey=buttonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentAltitude, Converter={x:Static my:IsEqualOrGreaterThanConverter.Instance}, ConverterParameter=24000}" Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
A more generic converter, usable with any comparable type, could be :
public class IsGreaterOrEqualThanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
IComparable v = value as IComparable;
IComparable p = parameter as IComparable;
if (v == null || p == null)
throw new FormatException("to use this converter, value and parameter shall inherit from IComparable");
return (v.CompareTo(p) >= 0);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
But in this case, the ConverterParameter must be interpreted with the same type as the value transmitted to your Converter. For example, to compare an int property 'MyIntProperty' with the contant int value 1, in your XAML, you can use this syntax :
<UserControl x:Class="MyNamespace.MyControl"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:genconverters="clr-namespace:MyConverterNamespace;assembly=MyConvertersAssembly">
<Grid>
<Grid.Resources>
<genconverters:IsGreaterOrEqualThanConverter x:Key="IsEqualOrGreaterThanConverter"/>
<sys:Int32 x:Key="Int1">1</sys:Int32>
</Grid.Resources>
<ComboBox IsEnabled="{Binding MyIntProperty,
Converter={StaticResource IsEqualOrGreaterThanConverter},
ConverterParameter={StaticResource Int1}}"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}"/>
</Grid>