WPF Load Images Based on Value - wpf

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>

Related

Set image on datagrid row header through xaml

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>

Devexpress( WPF GridControl) modify image inside a GridColumn using DataTrigger

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>

Wpf TreeView IsExpanded

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

Change Button Image Issue

Im working in WPF and I am trying to change the image of a button, I have created some triggers and Setters, but it is not working.
Here's my XAML code:
<Button BorderThickness="0" Height="23" HorizontalAlignment="Left" Margin="59,6,0,0" Name="topButton" Width="26" VerticalAlignment="Top"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" IsEnabled="False" >
<StackPanel>
<Image>
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=topButton, Path=Button.IsEnabled}" Value="True">
<Setter Property="Image.Source" Value="Images/MoveFirst_Enabled.bmp" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=topButton, Path=Button.IsEnabled}" Value="False">
<Setter Property="Image.Source" Value="Images/MoveFirst_Disabled.bmp" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
</Button>
I cant realize what I am doing wrong. Hope you can help me. Thank you in advance.
Remove the Button. for the Path. So instead of
Path=Button.IsEnabled
you should have
Path=IsEnabled
Example
<Button BorderThickness="0" Height="23" HorizontalAlignment="Left" Margin="59,6,0,0" Name="topButton" Width="26" VerticalAlignment="Top" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" IsEnabled="False">
<StackPanel>
<Image>
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=topButton, Path=IsEnabled}" Value="True">
<Setter Property="Source" Value="Images/MoveFirst_Enabled.bmp" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=topButton, Path=IsEnabled}" Value="False">
<Setter Property="Source" Value="Images/MoveFirst_Disabled.bmp" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
</Button>
I think you are not using the correct Uri string for the Source of the Image.
<Button BorderThickness="0" Height="23" HorizontalAlignment="Left" Margin="59,6,0,0" Name="topButton" Width="26" VerticalAlignment="Top"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" IsEnabled="False" >
<StackPanel>
<Image>
<Image.Style>
<Style TargetType="Image">
<!-- If you are using the Image as a Resource, you should use the following format.-->
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=topButton, Path=Button.IsEnabled}" Value="True">
<Setter Property="Image.Source" Value="assemblyname;component/Images/MoveFirst_Enabled.bmp" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=topButton, Path=Button.IsEnabled}" Value="False">
<Setter Property="Image.Source" Value="assemblyname;component/Images/MoveFirst_Disabled.bmp" />
</DataTrigger>
</Style.Triggers>
<!-- If you are using the Image as Content then you should use the below format.-->
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=topButton, Path=Button.IsEnabled}" Value="True">
<Setter Property="Image.Source" Value="Images/MoveFirst_Enabled.bmp" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=topButton, Path=Button.IsEnabled}" Value="False">
<Setter Property="Image.Source" Value="Images/MoveFirst_Disabled.bmp" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
</Button>
I hope it may help you...

How can I "Click Through" a control in WPF?

I have an order entry form that has a ListBox with a list of line items. I have my items template, and one of the values is a ComboBox in each of my Items.
Now, my form can also create Credit memo's in addition to purchase orders, but when I am creating a credit memo, I want to put the words "Credit Memo" over the list box, however, the TextBlock covers the ComboBox in two of my line items. I would like to pass my click event through the TextBlock to the ComboBoxes but I'm not sure how to do it.
This is what I have, ( Maybe I am coming at this totally wrong, I am kinda a noob with WPF )
<ListBox SelectionMode="Single" Grid.Row="2"
ItemsSource="{Binding Path=LineItems}" HorizontalContentAlignment="Stretch"
IsSynchronizedWithCurrentItem="True" Background="#66FFFFFF">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="WhiteSmoke"/>
<Setter Property="BorderThickness" Value="1" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsPartBackOrder}" Value="True">
<Setter Property="Background" Value="Orange" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type Entities:SalesOrderLineItem}" >
<OrderEntry:SalesOrderLineItemCreate DataContext="{Binding}" DeleteSalesOrderLineItem="DeleteSalesOrderLineItem" Margin="0,3,3,0" >
<OrderEntry:SalesOrderLineItemCreate.Resources>
<Style TargetType="{x:Type OrderEntry:SalesOrderLineItemCreate}">
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource=
{
RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}
},
Path=IsSelected
}" Value="True">
<Setter Property="Background" Value="LightBlue" />
<Setter Property="Foreground" Value="Black" />
</DataTrigger>
</Style.Triggers>
</Style>
</OrderEntry:SalesOrderLineItemCreate.Resources>
</OrderEntry:SalesOrderLineItemCreate>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Grid.Row="2"
Text="Credit Memo"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="48" Height="Auto"
FontStyle="Italic"
Foreground="Red"
Opacity=".25">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=OrderType}" Value="CR">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=OrderType}" Value="CU">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock IsHitTestVisible="False" .../>

Resources