Cant set Style in Trigger wpf - c#

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.

Related

Change style of a button at runtime in wpf with multibinding

I am trying to change the style of a button at runtime depending on a bool property. In addition to that, I am using the mahapps.metro framework.
My Code:
The view:
<UserControl.Resources>
<Style TargetType="{x:Type Button}" x:Key="firstStyle">
<Setter Property= "Style" Value="{StaticResource SquareButtonStyle}"/>
</Style>
<Style TargetType="{x:Type Button}" x:Key="secondStyle">
<Setter Property="Style" Value="{StaticResource AccentedSquareButtonStyle}"/>
</Style>
<conv:ButtonMultiConverter x:Key="styleConvert"/>
</UserControl.Resources>
The button:
<Button>
<Button.Style>
<MultiBinding Converter="{StaticResource styleConvert}">
<Binding Path="ValueFilter" />
<Binding Source="{StaticResource firstStyle}" />
<Binding Source="{StaticResource secondStyle}" />
</MultiBinding>
</Button.Style>
<iconPacks:PackIconModern Width="30" Height="15" Kind="edit"/>
</Button>
The converter:
public class ButtonMultiConverter: IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var firstStyle = values[1] as Style;
var secondStyle = values[2] as Style;
if (values[0] is bool)
return (bool)values[0] ? secondStyle : firstStyle;
return firstStyle;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
With this code I get always the following exception:
"style object is not allowed to affect the style property of the object to which it applies"
What should I change on the xaml code to prevent this exception.
The firstStyle and secondStyle resources are invalid. As the error message says, a Style applied to an element can not have a Setter that sets the Style property of that element.
They are however also redundant. Use SquareButtonStyle and AccentedSquareButtonStyle directly:
<Button.Style>
<MultiBinding Converter="{StaticResource styleConvert}">
<Binding Path="ValueFilter"/>
<Binding Source="{StaticResource SquareButtonStyle}"/>
<Binding Source="{StaticResource AccentedSquareButtonStyle}"/>
</MultiBinding>
</Button.Style>
If for any reason you really need firstStyle and secondStyle, declare them like this:
<Style x:Key="firstStyle" TargetType="Button"
BasedOn="{StaticResource SquareButtonStyle}"/>
<Style x:Key="secondStyle" TargetType="Button"
BasedOn="{StaticResource AccentedSquareButtonStyle}"/>

Update DataGrid styling on key press

I have a DataGrid that styles the background of rows based on if the row is listed as "to delete".
The rows change colour when loading into the table and when scrolling around, but do not immediately change.
I use "ctrl+del" to mark the selected rows for deletion.
How can I get the row to update on this keypress?
DataGrid Implementation
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="WhiteSmoke" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightGray" />
</Trigger>
<DataTrigger Value="True">
<DataTrigger.Binding>
<Binding>
<Binding.Converter>
<local:IsDeletedConverter/>
</Binding.Converter>
</Binding>
</DataTrigger.Binding>
<DataTrigger.Setters>
<Setter Property="Background" Value="OrangeRed"/>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
<Setter Property="Background">
<Setter.Value>
<Binding Path="">
<Binding.Converter>
<local:ValueToBrushConverter/>
</Binding.Converter>
</Binding>
</Setter.Value>
</Setter>
</Style>
</DataGrid.RowStyle>
Converter
public class IsDeletedConverter : IValueConverter
{
public object Convert(object values, Type targetType, object parameter, CultureInfo culture)
{
if (values is ExpandoObject eo)
{
if ((Application.Current.MainWindow as MainWindow).LoadedTable.ToDelete.Contains((int)ExpandoUtils.GetExpandoProperty(eo, "id")))
return true;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

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;
}

How to write trigger to textbox IskeyboardFocused property

I am trying to change other UI element visibility when textbox is focused. I think that isKeyboardFocused event may solve my problem. So i write my xaml as following.
<TextBox x:Name="SearchBox" Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch">
<i:Interaction.Triggers>
<e:PropertyChangedTrigger>
<i:Interaction.Behaviors>
<e:ConditionBehavior>
<e:ConditionalExpression>
<e:ComparisonCondition LeftOperand="{Binding SearchBox.IsKeyboardFocused}" Operator="Equal" RightOperand="rue" />
</e:ConditionalExpression>
</e:ConditionBehavior>
</i:Interaction.Behaviors>
<e:ChangePropertyAction TargetName="SearchLabel" PropertyName="Visibility" Value="Hidden" />
</e:PropertyChangedTrigger>
</i:Interaction.Triggers>
</TextBox>
<TextBlock x:Name="SearchLabel" Text="Search" FontStyle="Italic" Foreground="Gray" IsHitTestVisible="False" Visibility="Visible" />
This trigger is not working and i could'nt find the problem. What can i do to fix this problem or any other idea about it?
I would bind the Visibility to the IsKeyboardFocused property as follows:
<UserControl.Resources>
<YourNamespace:BoolToVisConverter x:Key="BoolToVis" />
</UserControl.Resources>
...
<TextBox x:Name="SearchBox" />
<Label Visibility="{Binding ElementName=SearchBox, Path=IsKeyboardFocused, Converter={StaticResource BoolToVis}, ConverterParameter='invert'}">hello</Label>
using a customized BoolToVisibilityConverter:
public class BoolToVisConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is bool)) throw new ArgumentException("bool value expected");
Visibility invisibleMode = (parameter == null || !(parameter is string) ||
!((string) parameter).ToLower().Contains("hidden"))
? Visibility.Collapsed
: Visibility.Hidden;
if ((parameter as string)?.ToLower().Contains("invert") ?? false) return (!(bool) value) ? Visibility.Visible : invisibleMode;
return ((bool) value) ? Visibility.Visible : invisibleMode;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The Converter parses given CommandParameter string for:
- "invert": true --> invisible, false --> visible
- "hidden": invisble case leads to Visibilitys.Hidden, otherwise it's Visibility.Collapsed
Well, I also find another answer which solves my problem easily. It may be also useful who has the same problem like me.
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Search" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>

Converter doesn't seem to fire at all times on mouse over

<Style TargetType="{x:Type dxg:GroupColumnSummaryControl}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<Binding Converter="{StaticResource c}"/>
</Setter.Value>
</Setter>
</Trigger>.
Whats wrong with this code here. my convertor doesnt seem to fire when i do a mouse over.
If i remove the convertor and assign the value as Red i can see the color.
this works perfectly fine
<Style TargetType="{x:Type dxg:GroupColumnSummaryControl}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red">
</Setter>
</Trigger>
This works for me: (I used RichTextBox)
<Window.Resources>
<my:ColorConverter x:Key="colorConverter" />
<Style TargetType="RichTextBox">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<Binding Converter="{StaticResource colorConverter}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
This is the converter:
public class ColorConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
return new SolidColorBrush(Colors.Red);
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return null;
}
}

Categories