WPF - TextBox won't respond to PropertyChanged in multibinding - c#

I have a textbox that should show hex value of a color. App can be in two states:
1) In edit mode (IsEdit==true) textbox binds to my model property and
2) when is not in edit mode (IsEdit==false) textbox binds to slider
representing RGB colors. Changing each color value with slider, hex value in textbox also changes and vice versa. Textbox is also binded to my model property so that I could save changes later.
Problem: When app is in edit mode changing textbox text property manually triggers converter and sends text value to model and sliders but when I change sliders, textbox text is changing but it doesn’t send data to model. Why?! I’ve tried everything I could think of. Changing binding mode, notifyontargetupdated… It should work… Can someone please explain.
I tried to simplify so if I missed anything important please let me know.
XAML code:
<Rectangle Grid.Column="0" Width="120" Height="120" Stroke="Black" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,0,0" Fill="{Binding ElementName=tbxHexColor, Path=Text, Converter={StaticResource HexToColorConverter}}"/>
<TextBox x:Name="tbxHexColor" CharacterCasing="Upper">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding IsEdit}" Value="False">
<Setter Property="Text" Value="{Binding SelectedColor.RGBHex}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsEdit}" Value="True">
<Setter Property="Text">
<Setter.Value>
<MultiBinding Converter="{StaticResource SlidersToHexConverter}" UpdateSourceTrigger="PropertyChanged">
<Binding ElementName="sliderRed" Path="Value"/>
<Binding ElementName="sliderGreen" Path="Value"/>
<Binding ElementName="sliderBlue" Path="Value"/>
<Binding Path="RGBHelper"/>
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Slider x:Name="sliderRed" Grid.Column="1" Grid.Row="0" Margin="0,5,0,3" Maximum="255">
<Slider.Style>
<Style TargetType="Slider">
<Style.Triggers>
<DataTrigger Binding="{Binding IsEdit}" Value="False">
<Setter Property="Value" Value="{Binding SelectedColor.RGBHex, Converter={StaticResource HexToRGBConverter}, ConverterParameter=red, FallbackValue=0}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsEdit}" Value="True">
<Setter Property="Value" Value="{Binding SelectedColor.RGBHex, Converter={StaticResource HexToRGBConverter}, ConverterParameter=red, Mode=OneTime}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Slider.Style>
</Slider>
<Slider x:Name="sliderGreen" Grid.Column="1" Grid.Row="1" Margin="0,3" Maximum="255">
<Slider.Style>
<Style TargetType="Slider">
<Style.Triggers>
<DataTrigger Binding="{Binding IsEdit}" Value="False">
<Setter Property="Value" Value="{Binding SelectedColor.RGBHex, Converter={StaticResource HexToRGBConverter}, ConverterParameter=green, FallbackValue=0}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsEdit}" Value="True">
<Setter Property="Value" Value="{Binding SelectedColor.RGBHex, Converter={StaticResource HexToRGBConverter}, ConverterParameter=green, Mode=OneTime}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Slider.Style>
</Slider>
<Slider x:Name="sliderBlue" Grid.Column="1" Grid.Row="2" Margin="0,3" Maximum="255">
<Slider.Style>
<Style TargetType="Slider">
<Style.Triggers>
<DataTrigger Binding="{Binding IsEdit}" Value="False">
<Setter Property="Value" Value="{Binding SelectedColor.RGBHex, Converter={StaticResource HexToRGBConverter}, ConverterParameter=blue, FallbackValue=0}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsEdit}" Value="True">
<Setter Property="Value" Value="{Binding SelectedColor.RGBHex, Converter={StaticResource HexToRGBConverter}, ConverterParameter=blue, Mode=OneTime}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Slider.Style>
</Slider>
Converters:
public class HexToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string input = "#" + value as string;
if (string.IsNullOrEmpty(input) || input == "#" || input.Length < 7)
{
input = "#00FFFFFF";
}
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(input));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class SlidersToHexConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string hex = "";
for (int i = 0; i < 3; i++)
{
int itemInt = System.Convert.ToInt32(values[i]);
if (itemInt != 0)
{
string a = itemInt.ToString("X");
if (a.Length == 1)
{
hex += "0" + a;
}
else
{
hex += a;
}
}
else
{
hex += "00";
}
}
return hex;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
object[] sliderValues = new object[4] { 0, 0, 0, "" };
if (value.ToString().Length == 6)
{
string r = value.ToString().Substring(0, 2);
string g = value.ToString().Substring(2, 2);
string b = value.ToString().Substring(4, 2);
double rr = int.Parse(r, NumberStyles.HexNumber);
double gg = int.Parse(g, NumberStyles.HexNumber);
double bb = int.Parse(b, NumberStyles.HexNumber);
sliderValues[0] = (object)rr;
sliderValues[1] = (object)gg;
sliderValues[2] = (object)bb;
}
sliderValues[3] = value.ToString();
return sliderValues;
}
}
public class HexToRGBConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return 0;
}
string hex = value.ToString();
string colorHex = "0";
switch (parameter.ToString())
{
case "red":
colorHex = hex.Substring(0, 2);
break;
case "green":
colorHex = hex.Substring(2, 2);
break;
case "blue":
colorHex = hex.Substring(4, 2);
break;
default:
break;
}
return int.Parse(colorHex, NumberStyles.HexNumber);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Tried everything in MultiBinding part of XAML. Changing: NotifyOnSourceUpdated, NotifyOnTargetUpdated, Mode, UpdateSourceTrigger... Nothing works.

Related

Change predefined style inside a control in xaml

I have the following style in App.xaml:
<Style TargetType="{x:Type Button}">
<Style.Resources>
<DataTemplate x:Key="Unpressed">
<Image Stretch="Uniform" Source="Img/button1.png"/>
</DataTemplate>
<DataTemplate x:Key="Pressed">
<Image Stretch="Uniform" Source="Img/button1_press.png"/>
</DataTemplate>
</Style.Resources>
<Setter Property="ContentTemplate" Value="{StaticResource Unpressed}"/>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource Pressed}"/>
</Trigger>
</Style.Triggers>
</Style>
I want to change the data template from my button, something like this:
<Button x:Name="Button2">
<Style>
<Style.Resources>
<DataTemplate x:Key="Unpressed">
<Image Stretch="Uniform" Source="../Img/button2.png"/>
</DataTemplate>
<DataTemplate x:Key="Pressed">
<Image Stretch="Uniform" Source="../Img/button2_press.png"/>
</DataTemplate>
</Style.Resources>
</Style>
</Button>
So basically, all my buttons have the same style but each button have an unique image, I need to change the DataTemplate of the style individually for each button
This is my proposed solution:
For the style:
<Application.Resources>
<local:ImgToDisplayConverter x:Key="ImgToDisplayConverter"/>
<local:ImgPressedToDisplayConverter x:Key="ImgPressedToDisplayConverter"/>
<Style TargetType="Image" x:Key="PressedButtonImageStyle">
<Setter Property="Source">
<Setter.Value>
<MultiBinding Converter="{StaticResource ImgToDisplayConverter}">
<Binding Path="Tag" RelativeSource="{RelativeSource AncestorType=Button}"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource AncestorType=Button}}" Value="true">
<Setter Property="Source">
<Setter.Value>
<MultiBinding Converter="{StaticResource ImgPressedToDisplayConverter}">
<Binding Path="Tag" RelativeSource="{RelativeSource AncestorType=Button}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Application.Resources>
For the Control:
<Button Tag="button1" Width="100" Height="100" HorizontalAlignment="Left">
<ContentControl>
<Image Stretch="Uniform" Style="{StaticResource PressedButtonImageStyle}" IsHitTestVisible="False"/>
</ContentControl>
</Button>
The Converters:
class ImgToDisplayConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string image = values[0].ToString();
string resourceName = String.Format("pack://application:,,,/{0}.png", image);
return new BitmapImage(new Uri(resourceName));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
class ImgPressedToDisplayConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string image = values[0].ToString();
string resourceName = String.Format("pack://application:,,,/{0}_pressed.png", image);
return new BitmapImage(new Uri(resourceName));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You can change the code depending on your needs.
I use this simple code and it works well(if you want to release the button from being pressed ,set timer).I hope this will help you..
xaml code
<Button Name="male" Height="318" Width="352" Click="male_Click" Margin="236,120,1332,642">
<Button.Background>
<ImageBrush ImageSource="pack://application:,,,/Imagesrc/logotype/USER_MALE.png" ></ImageBrush>
</Button.Background>
</Button>
pressed code
public void male_Click(object sender, RoutedEventArgs e)
{
System.Windows.Controls.Image img = new System.Windows.Controls.Image();
img.Source = new BitmapImage(new Uri(#"pack://application:,,,/maindocket;component/Imagesrc/logotype/USER_MALE_SELECTED.png"));
male.Content = img;
}

Cant set Style in Trigger wpf

i want to change style when toggle button checked
<ToggleButton.Style>
<Style TargetType="ToggleButton" BasedOn="{StaticResource ToggleButtonPrimary}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ButtonNude, Path=IsChecked}" Value="True">
<Setter Property="Style" Value="{StaticResource ToggleButtonDanger}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
but my code not work and app crash
As suggested by #clemens , the right way would be to have template and apply in controlTemplate with TargetName
There is one more (may be ugly) way:
On view:
<StackPanel>
<StackPanel.Resources>
<local:Myconverter x:Key="MyConverter" />
<Style TargetType="ToggleButton" x:Key="ToggleButtonPrimary">
<Setter Property="Background" Value="blue" />
</Style>
<Style TargetType="ToggleButton" x:Key="ToggleButtonDanger">
<Setter Property="Background" Value="Red" />
</Style>
</StackPanel.Resources>
<CheckBox Margin="20" x:Name="chk" />
<ToggleButton Width="100" Height="100" >
<ToggleButton.Style>
<MultiBinding Converter="{StaticResource MyConverter}">
<MultiBinding.Bindings>
<Binding ElementName="chk" Path="IsChecked"/>
<Binding RelativeSource="{RelativeSource AncestorType=StackPanel}"/>
</MultiBinding.Bindings>
</MultiBinding>
</ToggleButton.Style>
</ToggleButton>
</StackPanel>
Converter:
public class Myconverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if ((bool)values[0])
{
return (values[1] as FrameworkElement).Resources["ToggleButtonDanger"];
}
else
return (values[1] as FrameworkElement).Resources["ToggleButtonPrimary"];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Hope that helps.

How to color certain header columns and certain cells of a datagrid wpf

I was trying a example to color certain datagrids cell depending on a condition but do not know how to manage color of certain cells with code
In the following code, the third column will be red if date is even
I am using
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LoadSummaryMesh();
}
private void LoadSummaryMesh()
{
DataTable dt = new DataTable();
dt.Columns.Add("c1");
dt.Columns.Add("c2");
dt.Columns.Add("xxx", typeof(DateTime));
dt.Rows.Add("aa", "" , DateTime.Now.AddDays(0));
dt.Rows.Add("bb", "" ,DateTime.Now.AddDays(1));
dt.Rows.Add("cc", "" , DateTime.Now.AddDays(2));
this.dataGrid1.DataContext = dt;
}
}
public class MyBkColorConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
DataRowView drv = value as DataRowView;
if (drv != null)
{
DateTime dt = DateTime.Parse(drv[2].ToString());
if (dt.Day % 2 == 0) //If it's a even number day.
return Brushes.Red;
}
return Brushes.White;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
and xaml
<Window x:Class="SummaryMesh.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SummaryMesh"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MyBkColorConverter x:Key="bkColorCvrt"/>
<Style x:Key="LeftAlignmentColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource WrappedColumnHeaderStyle}">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
</Style>
<Style x:Key="soDataGrid_ColumnHeaderRotateStyle" TargetType="DataGridColumnHeader" >
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding}"
FontWeight="Bold" Width="90"
VerticalAlignment="Center" TextAlignment="Center"
HorizontalAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="270" />
</TextBlock.LayoutTransform>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</Window.Resources>
<Grid>
<DataGrid ItemsSource="{Binding}"
AutoGenerateColumns="False"
ColumnHeaderStyle ="{StaticResource soDataGrid_ColumnHeaderRotateStyle}"
Margin="22,12,18,19" Name="dataGrid1"
xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding c1}" Width="80" Header="c1" />
<DataGridTextColumn Binding="{Binding c2}" Width="80" Header="c2"/>
<DataGridTextColumn Binding="{Binding xxx}" Width="80" Header="xxx">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background">
<Setter.Value>
<Binding Converter="{StaticResource bkColorCvrt}"/>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
To get:
Now the question is how can I color only the second column header blue
and how to color [second column,second row] yellow (using the datatable I am using) ?
something similar to
For 'yellow' cell, you can do as third column.
Add a new converter:
public class MyBkColorConverter2 : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
DataRowView drv = value as DataRowView;
if (drv != null)
{
int rownum = drv.Row.Table.Rows.IndexOf(drv.Row);
if (rownum == 1)
{
return Brushes.Yellow;
}
}
return Brushes.White;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Add it in xaml:
...
<local:MyBkColorConverter2 x:Key="bkColorCvrt2"/>
...
<DataGridTextColumn Binding="{Binding c2}" Width="80" Header="c2">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource soDataGrid_ColumnHeaderRotateStyle}">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="Yellow"/>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.HeaderStyle>
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background">
<Setter.Value>
<Binding Converter="{StaticResource bkColorCvrt2}"/>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
For column header:
<DataGridTextColumn Binding="{Binding c2}" Width="80" Header="c2">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource soDataGrid_ColumnHeaderRotateStyle}">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="Yellow"/>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
First about 'yellow' cell you already have an answer, just change CellStyle for a second column as you did it for third column.
Second about header: Add style for your TextBlock at DataGridColumnHeader template, and set required triggers so they will change background, or wrap you TextBlock with grid and set it's background based on trigger.

Datatrigger not firing when using a converter

I have a rectangle which I want to set 4 different icons to based on if a value inside my page.cs is between certain values, for instance:
If value is 0 show icon 1.
if value is larger than 0 but smaller or equal to 0.25 show icon 2.
If value is >0.25 && value is <=0.5 show icon 3.
If value is >0.5 && value is <=0.75, show icon 4.
and If value is >0.75 && value is <=1 show icon 5.
Here's what my variable looks like:
private double _double = 0.25;
public double Volume
{
get
{
return _double;
}
set
{
_double = value;
OnPropertyChanged("Volume");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
I also have INotifyPropertyChanged set next to the partial class
And here's the converter I'm using:
[ValueConversion(typeof(double), typeof(int))]
public class VolumePicture : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (System.Convert.ToDouble(value) <= 0.25)
{
return 1;
}
else if (System.Convert.ToDouble(value) > 0.25 && System.Convert.ToDouble(value) <= 0.5)
{
return 2;
}
else if (System.Convert.ToDouble(value) > 0.5 && System.Convert.ToDouble(value) <= 0.75)
{
return 3;
}
else if (System.Convert.ToDouble(value) > 0.75 && System.Convert.ToDouble(value) <= 1)
{
return 4;
}
else
{
return 0;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
It basically takes an input and does exactly how I described in the first part.
Aaaand here's the XAML I have for the rectangle which I want to change the opacitymask for:
<Rectangle Height="20" Margin="0,2,0,0">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="#FF929292" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=VolumeButton}"
Value="True">
<Setter Property="Fill" Value="White" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource VolumePictureConverter}}" Value="5">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_mute}"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ResourceKey=VolumePictureConverter}}" Value="1">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_0}"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ResourceKey=VolumePictureConverter}}" Value="2">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_1}"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ResourceKey=VolumePictureConverter}}" Value="3">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_2}"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ResourceKey=VolumePictureConverter}}" Value="4">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_3}"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
This might look quite messy and for that, I'm sorry.
But, here's my problem: When I change the Volume variable during runtime, nothing seems to happen. I think it's the converter that's not firing, but I have NO idea why this is happening(!)
And since I'm really not that good with binding and converters and WPF in general, I've gotten stuck with this..
Anyone got an idea about what the troublemaker might be?
Thank you
One thing to note is that I didn't always have the "NowPlaying.Volume" path in there, I just tried a bunch of stuff.
And when I'm debugging I'm getting this in the output (which gets renamed to "Path error: 'Volume'" when I remove the Nowplaying.
System.Windows.Data Error: 40 : BindingExpression path error: 'NowPlaying' property not found on 'object' ''Rectangle' (Name='')'. BindingExpression:Path=NowPlaying.Volume; DataItem='Rectangle' (Name=''); target element is 'Rectangle' (Name=''); target property is 'NoTarget' (type 'Object')
It seems that you are binding to the Rectangle instead of it's DataContext. Rectangle doesn't have property Volume, hence you'll get binding error. Try to change your binding statement to something like this (notice this part : ...Path=DataContext.Volume...) :
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
.......
<Style.Triggers>
.......
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=DataContext.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource VolumePictureConverter}}"
Value="5">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_mute}"/>
</Setter.Value>
</Setter>
</DataTrigger>
.......
</Style.Triggers>
.......
</Style>
</Rectangle.Style>

Data Trigger conditions check in WPF

If any possible to give condition on DataTrigger?
<DataTrigger Binding="{Binding MessageBoxImage}" Value="{x:Static MessageBoxImage.Error}">
<Setter Property="Source" Value="../Images/Error48.png"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding MessageBoxImage}" Value="{x:Static MessageBoxImage.Hand}">
<Setter Property="Source" Value="../Images/Error48.png"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding MessageBoxImage}" Value="{x:Static MessageBoxImage.Stop}">
<Setter Property="Source" Value="../Images/Error48.png"></Setter>
</DataTrigger>
So, this is my Xaml code, in that Error,Hand,Stop all are setting same image
My question is any possible to give OR condition for these three values? (or one line statement)
Thanks,
You can use MultiDataTrigger for AND condition. As for OR condition you can use converter.
<Window.Resources>
<someNs:ORConverter x:Key = "ORConverter"/>
</Window.Resources>
....
<DataTrigger Value="True">
<DataTrigger.Binding>
<Binding Path="MessageBoxImage" Converter="{StaticResource ORConverter}">
<Binding.ConverterParameter>
<x:Array Type="MessageBoxImage">
<x:Static MemberType="MessageBoxImage" Member="Error" />
<x:Static MemberType="MessageBoxImage" Member="Information" />
<x:Static MemberType="MessageBoxImage" Member="Question" />
</x:Array>
</Binding.ConverterParameter>
</Binding>
</DataTrigger.Binding>
<Setter Property="Source" Value="../Images/Error48.png"></Setter>
</DataTrigger>
And the converter's code:
public class ORConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
var list = parameter as IList;
if (list == null)
return false;
foreach (var o in list)
{
if (Equals(o, value))
return true;
}
return false;
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException("Cannot convert back");
}
}
With the simple DataTrigger is meant to check for a single values. if Possible you could use the Multi-DataTrigger to check the multiple conditions.

Categories