Reputation: 81
I used the Datatemplate for Datagrid columns which is autogenerated set to true, I would like to bind the column Name in Datatemplate dynamically, so that I can use one Datatemplate for all columns, is it Possible??
I have tried with DataGridTemplateColumn and DataTemplate, but it looks like DataGridTemplateColumn I have to create for every Column, so proceed with DataTemplate.
Purpose of using DataTemplate is, based on the column value, it shows the image.
<Image Name="theImage" Width="40" Height="30" Source="../Resources/Help.png"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Col1}" Value="0,00">
<Setter TargetName="theImage" Property="Source" Value="../Resources/pmIcons/minus-256.png"/>
<DataTrigger Binding="{Binding Path=Col1}" Value="1,00">
<Setter TargetName="theImage" Property="Source" Value="../Resources/pmIcons/greenRoundTick.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Col1}" Value="2,00">
<Setter TargetName="theImage" Property="Source" Value="../Resources/pmIcons/redCross.png"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate>
<Image Name="theImage" Width="40" Height="30" Source="../Resources/Help.png"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Col2}" Value="0,00">
<Setter TargetName="theImage" Property="Source" Value="../Resources/pmIcons/minus-256.png"/>
<DataTrigger Binding="{Binding Path=Col2}" Value="1,00">
<Setter TargetName="theImage" Property="Source" Value="../Resources/pmIcons/greenRoundTick.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Col2}" Value="2,00">
<Setter TargetName="theImage" Property="Source" Value="../Resources/pmIcons/redCross.png"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Private Sub AutoGeneratingColumn(sender As Object, e As DataGridAutoGeneratingColumnEventArgs)
If e.PropertyName = "IsReadable" Or e.PropertyName = "HasValue" Then
e.Cancel = True
Exit Sub
End If
Dim oGrdTemplate As DataGridTemplateColumn = New DataGridTemplateColumn
oGrdTemplate.Header = e.Column.Header
oGrdTemplate.CellTemplate = CType(grdTotal.FindResource("test"), DataTemplate)
e.Column = oGrdTemplate
Expected: The above code works, but I have 40 columns so I have to duplicate the same DataTemplate for 40 times. I feel its not the better approach. I would like to bind the corresponding Column name as Col1, Col2, Col3 etc in every Columns. Its there a way to bind in Xaml well and good if not in code-behind is possible?
I tried with <DataTrigger Binding="{Binding Path=.}" Value="0,00">
does not work.
Upvotes: 1
Views: 281
Reputation: 81
I have referred @themightylc answer then
I have added the class cls_PMImageConverter,
<local:cls_PMImageConverter x:Key="PMImageConverter"/>,
<DataTemplate x:Key="colTemplate_Col1">
<Image Source="{Binding Path=Col1, Converter={StaticResource PMImageConverter}}" /> </DataTemplate>
<DataTemplate x:Key="colTemplate_Col2">
<Image Source="{Binding Path=Col2, Converter={StaticResource PMImageConverter}}" /> </DataTemplate>
etc till col40
and called this template in AutogeneratedColumn event as
Dim oGrdTemplate As DataGridTemplateColumn = New DataGridTemplateColumn
oGrdTemplate.Header = e.Column.Header
oGrdTemplate.CellTemplate = CType(grdTotal.FindResource("colTemplate_"+e.PropertyName), DataTemplate)
e.Column = oGrdTemplate `
It works.. But still, its not dynamic rite? Can I improve this code further??
Upvotes: 0
Reputation: 324
There is plenty room of improvement your design, for example you should have an Enumeration
as your columns instead of 40 distinctive named objects.
But even with your current design, you can implement an IValueConverter
that directly turns the value to the correct image URI and then you can bind the Image
directly to your source Value through the converter.
Off the top of my head, untested:
Write a Converter:
<ValueConversion(GetType(Double), GetType(String))>
Public Class MyValueToImageConverter
Implements IValueConverter
Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
Try
If CDbl(value) = 0.0 Then Return "../Resources/pmIcons/minus-256.png"
If CDbl(value) = 1.0 Then Return "../Resources/pmIcons/greenRoundTick.png"
If CDbl(value) = 2.0 Then Return "../Resources/pmIcons/redCross.png"
Catch ex As Exception
'this is okay for our purpose
End Try
Return "../Resources/Help.png"
End Function
Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
Throw New NotImplementedException()
End Function
End Class
Embed in in your Resources (Window
or Page
etc)
<Window.Resources>
<local:MyValueToImageConverter x:Key="myConverter"/>
</Window.Resources>
And bind your columns like this:
<Image Source="{Binding Col1,Converter={StaticResource myConverter}}" />
You can then wrap this functionality into a UserControl
making use of the ominous "Tag" DependencyProperty
<UserControl
x:Class="StatusIcon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d"
>
<UserControl.Resources>
<local:MyValueToImageSourceConverter x:Key="_conv" />
</UserControl.Resources>
<Image Source="{Binding Tag, RelativeSource={RelativeSource AncestorType={x:Type local:StatusIcon}}, Converter={StaticResource _conv}}" />
</UserControl>
And end up with something as neat and clean as this:
<local:StatusIcon Tag="{Binding Col1}"/>
You can then further improve this by replacing Tag with your own DependencyProperty
called Value or something similar
Upvotes: 0