I am using a WPF Devexpress GridControl and I have a column that contains an image. I want to modify the Image using a DataTrigger. Here is the XAML:
<dxg:GridColumn Header="{Binding Source={StaticResource MainWindowResources}, Path=Resource.Status}"
FieldName="SaveStatus"
MinWidth="60"
Width="60"
ReadOnly="True"
>
<dxg:GridColumn.CellTemplate>
<DataTemplate>
<Image HorizontalAlignment="Center"
VerticalAlignment="Center"
Style="{StaticResource ImageStatusStyle}">
</Image>
</DataTemplate>
</dxg:GridColumn.CellTemplate>
</dxg:GridColumn>
and the style:
<Style TargetType="{x:Type Image}" x:Key="ImageStatusStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Data.SaveStatus, UpdateSourceTrigger=
PropertyChanged}" Value="{x:Static enums:SaveState.DoneSuccesfuly}">
<Setter Property="Source" Value="..\Icons\StatusOk.png" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Data.SaveStatus, UpdateSourceTrigger=
PropertyChanged}" Value="{x:Static enums:SaveState.DoneUnsuccesfuly}">
<Setter Property="Source" Value="..\Icons\StatusError.png" />
</DataTrigger>
</Style.Triggers>
</Style>
This doesn't work. What am I doing wrong? Is there a better solution to this problem?
I managed to find the solution. The problem was the datatrigger binding instead of Data.SaveStatus should be RowData.Row.SaveStatus:
<Style.Triggers>
<DataTrigger Binding="{Binding Path=RowData.Row.SaveStatus, UpdateSourceTrigger=PropertyChanged}" Value="{x:Static enums:SaveState.DoneSuccesfuly}">
<Setter Property="Source" Value="..\Icons\StatusOk.png"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=RowData.Row.SaveStatus, UpdateSourceTrigger=PropertyChanged}" Value="{x:Static enums:SaveState.DoneUnsuccesfuly}">
<Setter Property="Source" Value="..\Icons\StatusError.png"></Setter>
</DataTrigger>
</Style.Triggers>
Try accessing you images like this:
<Style TargetType="{x:Type Image}" x:Key="ImageStatusStyle">
<Style.Triggers>
<Setter Property="Source" Value="/ApplicationName;component/Icons/StatusOk.png" />
<DataTrigger Binding="{Binding Path=Data.SaveStatus, UpdateSourceTrigger=
PropertyChanged}" Value="{x:Static enums:SaveState.DoneUnsuccesfuly}">
<Setter Property="Source" Value="/ApplicationName;component/Icons/StatusError.png" />
</DataTrigger>
</Style.Triggers>
</Style>
Related
I have a List<object> which contains a list of of values for each object which I want to access and create a set image based on the values - don't really want to use a Converter.
I have the below which works:
<Image x:Name="Desk1" Grid.Column="1" Grid.Row="2" Width="50" Height="50">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Office[0].Desks[0].Status} Value="0">
<Setter Property="Source" Value="pack:///application:,,,/Resources/DeskAvailable.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Office[0].Desks[0].Status} Value="1">
<Setter Property="Source" Value="pack:///application:,,,/Resources/DeskUnavailable.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Office[0].Desks[0].Status} Value="2">
<Setter Property="Source" Value="pack:///application:,,,/Resources/DeskUnknown.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
But I don't want to have to write all this for many desks.
So I've created a Resource:
<Windows.Resources>
<DataTemplate x:Key = "DeskImage">
<Image>
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Value="0">
<Setter Property="Source" Value="pack:///application:,,,/Resources/DeskAvailable.png"/>
</DataTrigger>
<DataTrigger Value="1">
<Setter Property="Source" Value="pack:///application:,,,/Resources/DeskUnavailable.png"/>
</DataTrigger>
<DataTrigger Value="2">
<Setter Property="Source" Value="pack:///application:,,,/Resources/DeskUnknown.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Windows.Resources>
Which I was hoping to access for each image and just pass it the value in Office[x].Desk[x].Status to determine which image to load. But this is the bit I'm unsure on how to create an image type in xaml and pass the value to the static resource.
Something like:
<Image x:Name="Desk1" Grid.Column="1" Grid.Row="2" Width="50" Height="50">
[pseudocode]
Bind to Office[x].Desks[x].Status
Pass data to Resource and load correct image
[/pseudo]
</image>
You may consider using nested ItemsControls.
<ItemsControl ItemsSource="{Binding Office}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Desks}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Width="50" Height="50">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="0">
<Setter Property="Source" Value="pack:///application:,,,/Resources/DeskAvailable.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="1">
<Setter Property="Source" Value="pack:///application:,,,/Resources/DeskUnavailable.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="2">
<Setter Property="Source" Value="pack:///application:,,,/Resources/DeskUnknown.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I tried to setup a Datagrid so that I have an image in the RowHeader to show the status of each object that is listed.
To achieve that, I have a IsTaskCompletedSuccessfully nullable boolean property in my view model.
In my resources, I added an image with the following style:
<DataGrid.Resources>
<Image x:Name="editImage"
x:Key="rowHeaderTemplate"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="16"
Margin="1,0">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding IsTaskCompletedSuccessfully}" Value="true">
<Setter Property="Source" Value="/RFiDGear;component/Resources/confirm.ico"/>
</DataTrigger >
<DataTrigger Binding="{Binding IsTaskCompletedSuccessfully}" Value="false">
<Setter Property="Source" Value="/RFiDGear;component/Resources/error.ico"/>
</DataTrigger >
<DataTrigger Binding="{Binding IsTaskCompletedSuccessfully}" Value="{x:Null}">
<Setter Property="Source" Value="/RFiDGear;component/Resources/wait.ico"/>
</DataTrigger >
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataGrid.Resources>
below i have the rowheaderstyle:
<DataGrid.RowHeaderStyle>
<Style TargetType="{x:Type DataGridRowHeader}">
<Setter Property="Content" Value="{StaticResource rowHeaderTemplate}"/>
</Style>
</DataGrid.RowHeaderStyle>
Unfortunately it only works on the last row/object added not on all rows. What did i miss here?!
Edit1:
I edited the Style to a RowHeaderTemplate. Later i figured out that databinding isn't working correctly this way. My Image Source won't update. There are no binding errors in the output window at runtime.
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<Image x:Name="editImage"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="16"
Margin="1,0">
</Image>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsTaskCompletedSuccessfully}" Value="True">
<Setter TargetName="editImage" Property="Source" Value="/RFiDGear;component/Resources/confirm.ico"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsTaskCompletedSuccessfully}" Value="False">
<Setter TargetName="editImage" Property="Source" Value="/RFiDGear;component/Resources/error.ico"/>
</DataTrigger>
<!--<DataTrigger Binding="{Binding IsTaskCompletedSuccessfully}" Value="{x:Null}">
<Setter TargetName="editImage" Property="Source" Value="/RFiDGear;component/Resources/wait.ico"/>
</DataTrigger>-->
</DataTemplate.Triggers>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
Got it working. I have to work with relativesource to find the datacontext.
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<Image x:Name="editImage"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="16"
Margin="1,0">
</Image>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridRow}, Path=DataContext.IsTaskCompletedSuccessfully}" Value="True">
<Setter TargetName="editImage" Property="Source" Value="/RFiDGear;component/Resources/confirm.ico"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridRow}, Path=DataContext.IsTaskCompletedSuccessfully}" Value="False">
<Setter TargetName="editImage" Property="Source" Value="/RFiDGear;component/Resources/error.ico"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridRow}, Path=DataContext.IsTaskCompletedSuccessfully}" Value="{x:Null}">
<Setter TargetName="editImage" Property="Source" Value="/RFiDGear;component/Resources/wait.ico"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
I would like to change the fill of a rectangle based on a Textblock text
My Textblock
<TextBlock Name="lblOk" Text="OK" Foreground="Black" FontSize="20" FontWeight="Medium" />
My Datatrigger:
<Style x:Key="RectangleFill" TargetType="Rectangle">
<Setter Property="Fill" Value="Blue"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName="lblOk, Path=Text}" Value="OK">
<Setter Property="Fill" Value="#FF008C00" />
</DataTrigger>
</Style.Triggers>
</Style>
My Datatrigger doesnt work, seems the Path=Text is wrong. What is the correct Path?
Please check this code, it is working
<Window.Resources>
<Style x:Key="RectangleFill" TargetType="Rectangle">
<Setter Property="Fill" Value="Blue" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lblOk, Path=Text}" Value="OK">
<Setter Property="Fill" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<TextBlock Name="lblOk" Text="OK" Foreground="Black" FontSize="20" FontWeight="Medium" />
<Rectangle Width="100"
Height="50" Style="{StaticResource RectangleFill}">
<Rectangle.Resources>
</Rectangle.Resources>
</Rectangle>
</StackPanel>
My code is working. I had typo mistake as shwon in comment.
<Style x:Key="RectangleFill" TargetType="Rectangle">
<Setter Property="Fill" Value="Blue"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lblOk, Path=Text}" Value="OK">
<Setter Property="Fill" Value="#FF008C00" />
</DataTrigger>
</Style.Triggers>
</Style>
I have the following markup:
<Button Name="m_SaveButton" Command="{Binding SaveCommand}">
<StackPanel>
<Image Source="{StaticResource IconSave16}">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}}" Value="False">
<Setter Property="Source" Value="{StaticResource IconSaveInactive16}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Label Content="Save" />
</StackPanel>
</Button>
I want to change the Image nested inside the Button when Button.IsEnabled is false. The markup above is not working.
I was trying to use Meleak's code found here: WPF Mouseover Trigger Effect for Child Controls
Does anyone can suggest me a solution for this?
Thank you in advance!
You can't change a local value in style because of Value Precedence. This should work.
<Image>
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{StaticResource IconSave16}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}}" Value="False">
<Setter Property="Source" Value="{StaticResource IconSaveInactive16}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
I tried to bind to IsExpanded property in Hierarchical template with another context.
<HierarchicalDataTemplate x:Key="TreeView1" ItemsSource="{Binding Path=Folders}" >
<StackPanel Margin="5,5,5,5" Orientation="Horizontal">
<StackPanel Name="spinCont">
<ModulesUpToDateChecker1:Spinner Width="20" x:Name="Spin" FolderContext="{Binding}" StateContext="{Binding Path=State}"></ModulesUpToDateChecker1:Spinner>
<Image x:Name="imgFolderIcon" Width="16" Visibility="Hidden"
Source="/ModulesUpToDateChecker;component/Resources/FolderClosed16.png">
<Image.Triggers>
</Image.Triggers>
</Image>
<Image VerticalAlignment="Center" x:Name="imgFolderItem"
Source="{Binding Path=State, Converter={StaticResource stateFolderConverter}}">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsLast}" Value="true"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Collapsed"></Setter>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
<StackPanel DataContext="{Binding Path=Modules}">
<ModulesUpToDateChecker1:Spinner Width="20">
<ModulesUpToDateChecker1:Spinner.Style>
<Style TargetType="{x:Type ModulesUpToDateChecker1:Spinner}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Animation}" Value="True" >
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</ModulesUpToDateChecker1:Spinner.Style>
</ModulesUpToDateChecker1:Spinner>
<Image VerticalAlignment="Center"
Source="{Binding Path=State, Converter={StaticResource stateImageConverter}}">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Animation}" Value="True" >
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
<TextBlock Text="{Binding Path=Name}" Margin="10,0,0,0"></TextBlock>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<!--<Trigger Property="{Binding}" Value="true">
<Setter TargetName="imgFolderIcon" Property="Source" Value="/ModulesUpToDateChecker;component/Resources/Error.png" />
</Trigger>-->
**<DataTrigger Binding="{Binding Path=IsExpanded}" Value="true">
<Setter TargetName="imgFolderIcon" Property="Source" Value="/ModulesUpToDateChecker;component/Resources/Error.png" />
</DataTrigger>**
doest work
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
I have the "Folder" context (its hierarchical object) but how can i bind to theTreeView properties in HierarchicalDataTemplate.Triggers? When i start this, output shows that there is no IsExpanded property in Folder object. So, i have wrong context.
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=IsExpanded}" Value="true">
<Setter TargetName="imgFolderIcon" Property="Source" Value="/Resources/FolderExpanded.png" />
</DataTrigger>
Easy