<DataTemplate>
<Image Name="ServerImageSetter" Source="{svg2Xaml:SvgImage ServerAdministrator2;component/Images/test1.svg}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding ServerKindTrigger}" Value="0">
<Setter TargetName="ServerImageSetter" Property="Source" Value="{svg2Xaml:SvgImage ServerAdministrator2;component/Images/test2.svg}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ServerKindTrigger}" Value="1">
<Setter TargetName="ServerImageSetter" Property="Source" Value="{svg2Xaml:SvgImage ServerAdministrator2;component/Images/test3.svg}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ServerKindTrigger}" Value="2">
<Setter TargetName="ServerImageSetter" Property="Source" Value="{svg2Xaml:SvgImage ServerAdministrator2;component/Images/test3.svg}"/>
</DataTrigger>
</DataTemplate
In my C# code I switch the kind of my value to 0-2 and that should change the image. But the change doesn't work.
public int ServerKindTrigger
{
get { return _serverKindTrigger; }
set { _serverKindTrigger = value;
RaisePropertyChanged();
}
}
//Here I switch my serverkind and wanna change the image value
switch (_serverKind)
{
case Servers.test: _serverKindTrigger = 0;
Besides setting the backing field _serverKindTrigger instead of the property ServerKindTrigger, and thus not firing the PropertyChangedEvent, you are directly setting the Source property of the Image control:
<Image Source="{svg2Xaml:SvgImage ServerAdministrator2;component/Images/test1.svg}"/>
This so-called local value always has a higher precedence than the values from the Setters in the DataTriggers. For reference, see Dependency Property Value Precedence.
Change your XAML to this:
<Image>
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{svg2Xaml:SvgImage ServerAdministrator2;component/Images/test1.svg}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ServerKindTrigger}" Value="0">
<Setter Property="Source" Value="{svg2Xaml:SvgImage ServerAdministrator2;component/Images/test2.svg}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ServerKindTrigger}" Value="1">
<Setter Property="Source" Value="{svg2Xaml:SvgImage ServerAdministrator2;component/Images/test3.svg}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ServerKindTrigger}" Value="2">
<Setter Property="Source" Value="{svg2Xaml:SvgImage ServerAdministrator2;component/Images/test3.svg}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
You are changing local fields and not the property, which is why it isn't triggering binding updates.
Change your switch/case assignment to assign ServerKindTrigger property.
switch (_serverKind)
{
case Servers.test: ServerKindTrigger = 0;
Related
I am currently working on a small c# wpf project. I fill my datagrid programmatically and I want to change one cells color in the style without affecting the whole row. I do this after changing the DataGrid Rowstyle.
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Gebucht}" Value="True">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=dringendeBuchung}" Value="True">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Dringend}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
The rowstyle works fine, but if for example "Gebucht" is true and Dringend is true too I want to display the whole row in green except for the Cell which has the Dringend boolean.
Thank you for your help
The rowstyle works fine, but if for example "Gebucht" is true and Dringend is true too I want to display the whole row in green except for the Cell which has the Dringend boolean.
Then you should set the CellStyle property of the specific column instead of setting the CellStyle property for the entire DataGrid, e.g.:
<DataGrid ... >
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Gebucht}" Value="True">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=dringendeBuchung}" Value="True">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Dringend}" Header="Dringend">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Dringend}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<!-- + other columns... -->
</DataGrid.Columns>
</DataGrid>
I am VERY new to WPF AND C#, so there may be a much better way to accomplish what I am attempting. Therefore, I am open to other methods.
As far as what I've got, I am trying to program a Digital VMB (Visual Management Board) for the maintenance department where I work. They want a section to display the number of days our plant has gone without an accident: "Days Safe". I successfully have the binding set for this TextBlock:
<TextBlock Text="{Binding DaysSafe}" FontSize="60" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" >
I have a series of DataTriggers to change the Foreground color of the text to a certain color, based on the value of the text. Basically, I want the DaysSafe text to be:
Red when 0
Orange when 1 and so on (you can see the colors in my code below):
<StackPanel VerticalAlignment="Center" >
<TextBlock Text="{Binding DaysSafe}" FontSize="60" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" >
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers >
<DataTrigger Binding="{Binding DaysSafe}" Value="0">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="1">
<Setter Property="Foreground" Value="OrangeRed" />
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="2">
<Setter Property="Foreground" Value="Orange" />
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="3">
<Setter Property="Foreground" Value="Yellow" />
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="4">
<Setter Property="Foreground" Value="Yellow" />
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="5">
<Setter Property="Foreground" Value="GreenYellow" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
This functions correctly, the colors change when the days are lower. HOWEVER, I would like for the foreground color to "Default" to green when the value of DaysSafe is over 5. Right now, any value above 5 is black when I want it to be green. I tried adding the foreground="green" attribute in the first TextBlock section, but this overrides the DataTriggers and the foreground is always green.
Any help with how I may create a default value for the foreground?
Thanks.
You could just add a setter that sets the default Foreground of the TextBlock to Green:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green" />
<Style.Triggers >
<DataTrigger Binding="{Binding DaysSafe}" Value="0">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="1">
<Setter Property="Foreground" Value="OrangeRed" />
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="2">
<Setter Property="Foreground" Value="Orange" />
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="3">
<Setter Property="Foreground" Value="Yellow" />
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="4">
<Setter Property="Foreground" Value="Yellow" />
</DataTrigger>
<DataTrigger Binding="{Binding DaysSafe}" Value="5">
<Setter Property="Foreground" Value="GreenYellow" />
</DataTrigger>
</Style.Triggers>
</Style>
I have this DataGrid and I have been playing with setting the background colour of selected cells:
<DataGridTextColumn Header="Next Study" Binding="{Binding NextStudy}">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Text" Value="25">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="ToolTip" Value="{Binding NextStudyDescription}" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
It works as you can see:
But that is not really what I want. Instead I would like to highlight all cells where the value is greater than or equal to 18. So I tried:
<DataGridTextColumn Header="Next Study" Binding="{Binding NextStudy}">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{NextStudy Converter={StaticResource IsEqualOrGreaterThanConverter}, ConverterParameter=18}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="ToolTip" Value="{Binding NextStudyDescription}" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
It doesn't like: <DataTrigger Binding="{NextStudy
In addition, I would like to do this background test if the element comboActiveStudentAssignmentType selected index is 0, 1 or 2. Otherwise it does not need to do this highlighting.
Thanks.
You have a syntax error: Binding is the property name, you still have to declare it as a Binding
<DataTrigger Binding="{Binding NextStudy, Converter={StaticResource IsEqualOrGreaterThanConverter}, ConverterParameter=18}" Value="True">
As for the second part of the question, you can use a MultiDataTrigger. The conditions in the MultiDataTrigger have to ALL be true for the trigger to execute the setters. You will probably need to write another converter to transform your AssignmentType to True/False and you should be set.
Here's a quick example:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding NextStudy, Converter={StaticResource IsEqualOrGreaterThanConverter}, ConverterParameter=18}" Value="True"/>
<Condition Binding="{Binding comboActiveStudentAssignmentType, Converter={StaticResource YourOtherConverter}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="Red"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
I have a TextBlock and I want to set the property Visibility to Collapsed when the TextBlock has no text. I wonder me, for sure there should be a better way to check if the Lenght of the property Text is equal than 0.
<TextBlock Name="TextBlockHeader" Foreground="White" FontSize="18" FontWeight="Bold" Text="{Binding Header}" Margin="0,0,0,25">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=TextBlockHeader, Path=Text.Length}" Value="0">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Here I have to define a name for the TextBlock and I can reference it in the Datatrigger Binding="{Binding ElementName=TextBlockHeader, Path=Text.Length}"
But how can I achieve the same without having to define a name for the TextBlock?
You would usually use Triggers instead of DataTriggers, and compare the Text property to either null or an empty string.
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="Text" Value="">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
As the TextBlock class seems to coerce the Text property value to be non-null, it may be sufficient to have only the second Trigger for an empty string.
I have a check box that I want to collapse when a value is any value except one.
So I would like to do something like:
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ucPrincipal, Path=DataContext.MyProperyViewMode}" Value<>"MyValue">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
Of course, the value in the data trigger can't use the <> comparer, but that's the idea. MyPropertyViewModel is a value of an enumeration.
Since you have only one value when it should be visible you can simply invert your condition. By default set Visibility to Collapsed and only when it's that value trigger Visible
<CheckBox.Style>
<Style TargetType="CheckBox">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ucPrincipal, Path=DataContext.MyProperyViewMode}" Value="MyValue">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
You can use a IValueConverter. Suppose that your implementation is called YourConverter.
This is the Convert method:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
YourEnum enumValue = (YourEnum)value;
return enumValue == YourEnum.WrongValue;
}
So your DataTrigger will be:
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ucPrincipal, Path=DataContext.MyProperyViewMode, Converter={StaticResource YourConverter}}" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
Of course you have to declare the converter as a resource.