I have the DataTemplate below, which decides what .png to show based on the DirType. Currently, if we get DirType of 3, we show ./images/file.png
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=DirType}" Value="0">
<Setter Property="Image.Source" TargetName="img" Value="./Images/MyComputer.jpg"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=DirType}" Value="1">
<Setter Property="Image.Source" TargetName="img" Value="./Images/diskdrive.png"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=DirType}" Value="2">
<Setter Property="Image.Source" TargetName="img" Value="./Images/folder.png"></Setter>
<Setter Property="Text" TargetName="ObjType" Value="File Folder"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=DirType}" Value="3">
<Setter Property="Image.Source" TargetName="img" Value="./Images/file.png"></Setter>
<Setter Property="Text" TargetName="ObjType" Value="{Binding Ext}"></Setter>
<Setter Property="Visibility" TargetName="ObjSize" Value="Visible"></Setter>
<Setter Property="Text" TargetName="ObjSize" Value="{Binding Size}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True" >
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Then I use it in a ListBox:
<ListBox x:Name="dirList" Grid.ColumnSpan="3" IsSynchronizedWithCurrentItem="True"
ItemTemplate="{StaticResource DirViewTemplate}" BorderThickness="0"
HorizontalContentAlignment="Left" VerticalContentAlignment="Top"
Grid.Column="0" Grid.Row="1"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedItem="{Binding Path=CurrentItem,Mode=OneWayToSource}"
MouseDoubleClick="dirList_MouseDoubleClick"
KeyDown="dirList_KeyDown">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" ItemWidth="220"></WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Now, I want to dynamically change the image displayed for file type value = 3 based on their file types. Before all files have the same icon displayed in the list box but now I want them to pull the icons displayed in Windows explorer. I tried to access the DataTemplate dynamically while adding the items to the list, but I couldnt get it to work.
Any advice?
Use a MultiDataTrigger. This defines a number of conditions, all of which much evaluate to true for the trigger's setters to be applied.
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=DirType}" Value="3" />
<Condition Binding="{Binding Path=Ext}" Value="txt" />
</MultiDataTrigger.Conditions>
<Setter TargetName="img" Property="Source" Value="./Images/txt-file.png" />
</MultiDataTrigger>
Here you have two conditions, one bound to the DirType property value, the other bound to the Ext property value. If DirType is "3" and Ext is "txt", then the setter will be applied (ie. the image source will change to use a different image file).
Just repeat the trigger in the XAML, changing the binding values, to deal with other file types.
Related
Good Evening Everyone,
I am trying to change a WPF ListView ContextMenu header depending on a column value from said ListView. Specifically I want to change it from Enable to Disable (and vice-versa) when a column binded to the value of STATUS = "Y"(hold) or "N"(not on hold). I have tried the following:
<ContextMenu.Resources>
<Style TargetType="{x:Type MenuItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding STATUS}" Value="Y">
<Setter Property="Header" Value="Enable" />
</DataTrigger>
<DataTrigger Binding="{Binding STATUS}" Value="N">
<Setter Property="Header" Value="Disable" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContextMenu.Resources>
2ND Attempt:
<ListView.ContextMenu>
<ContextMenu x:Name="cmlv">
<MenuItem x:Name="cmdisableenable">
<MenuItem.Resources>
<Style TargetType="{x:Type MenuItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding STATUS}" Value="Y">
<Setter Property="Header" Value="Enable" />
</DataTrigger>
<DataTrigger Binding="{Binding STATUS}" Value="N">
<Setter Property="Header" Value="Disable" />
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Resources>
</MenuItem>
</ContextMenu>
</ListView.ContextMenu>
<MenuItem>
<MenuItem.Resources>
<Style TargetType="{x:Type MenuItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding STATUS}" Value="Y">
<Setter Property="Header" Value="Enable" />
</DataTrigger>
<DataTrigger Binding="{Binding STATUS}" Value="N">
<Setter Property="Header" Value="Disable" />
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Resources>
</MenuItem>
You have apply style on MenuItem so depends on status the header will be Disable or Enable and make sure u dont assign any value to header
I am trying to collapse a column according to a condition with this code:
<DataGridTextColumn Header="MyColumn" Binding="{Binding MyProperty}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Width" Value="0cm"/>
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ThisView, Path=DataContext.MyboolProperty}" Value="true">
<Setter Property="Width" Value="2.5cm"/>
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
The problem is that the column is not complete collapsed, I can see a part of the column.
I have tried this code too:
<DataGridTextColumn Header="MyColumn" Binding="{Binding MyProperty}"
Width="0cm"
Visibility="Collapsed">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ThisView, Path=DataContext.MyboolProperty}" Value="true">
<Setter Property="Width" Value="2.5cm"/>
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
In this case the column is collapsed as expected, but then if the property if the trigger is true, the column is still collapsed.
Also I have tried this option:
<DataGridTextColumn Header="MyColumn" Binding="{Binding MyProperty}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ThisView, Path=DataContext.MyboolProperty}" Value="true">
<Setter Property="Width" Value="2.5cm"/>
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=ThisView, Path=DataContext.MyboolProperty}" Value="false">
<Setter Property="Width" Value="0cm"/>
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
But the behavior is the same than first option, it is not full collapsed but it works when the property of the trigger is true.
Your data trigger is located inside column header template, therefore it can only change properties of column header (not a complete column, i.e. cells).
There is no Style for DataGridTextColumn, so you can't use DataTrigger. But converter should do.
However, another problem is that columns aren't in visual tree, so you can't use ElementName or RelativeSource, they simply won't work. There is an easy workaround however. Then your column will look like this:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="converter" />
<local:BindingProxy x:Key="proxy" Data="{Binding}" />
</Window.Resources>
...
<DataGridTextColumn Header="MyColumn"
Binding="{Binding MyProperty}"
Visibility="{Binding Data.MyboolProperty, Source={StaticResource proxy}, Converter={StaticResource converter}}" />
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 a RadTreeView and trying to use stye triggers for disabling few nodes:
<telerikNavigation:RadTreeView ItemTemplate="{StaticResource HierarchyItemsTreeItemTemplate}">
<telerikNavigation:RadTreeView.Style>
<Style TargetType="telerikNavigation:RadTreeView">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TreeViewItem}, Converter={StaticResource converter}}" Value="true">
<Setter Property="IsEnabled" Value="false"/>
</DataTrigger>
</Style.Triggers>
</Style>
</telerikNavigation:RadTreeView.Style>
</telerikNavigation:RadTreeView >
But this gives me error:
The attachable property Triggers was not found in Style
You don't seem to specify the property your Style should apply to which is the telerikNavigation:RadTreeView.Style. As of now you got a Style as the Content of the TreeView
Try:
<telerikNavigation:RadTreeView ItemTemplate="{StaticResource HierarchyItemsTreeItemTemplate}">
<telerikNavigation:RadTreeView.Style> <!-- Missing Line from original Code -->
<Style TargetType="telerikNavigation:RadTreeView">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType=TreeViewItem},
Converter={StaticResource converter}}"
Value="true">
<Setter Property="IsEnabled"
Value="false" />
</DataTrigger>
</Style.Triggers>
</Style>
</telerikNavigation:RadTreeView.Style> <!-- Missing Line from original Code -->
</telerikNavigation:RadTreeView>
I'm trying to have a button in a disabled state until both DataGrids have at least one selected item. Currently it remains in a Enabled state.
<Button MaxWidth="200" Grid.Column="0" x:Name="Add" Content="{x:Static UiStrings:Labels.Add}" >
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=SelectedIndex, ElementName=EconomicFactors}" Value="-1"></Condition>
<Condition Binding="{Binding Path=SelectedIndex, ElementName=TargetTypes}" Value="-1"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Regards,
In MultiDataTrigger all conditions has to be true. I think simplest solution is to replace MultiDataTrigger with two DataTrigger
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SelectedIndex, ElementName=EconomicFactors}" Value="-1">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=SelectedIndex, ElementName=TargetTypes}" Value="-1">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>