0

My first WPF application (please be gentle!), and I'm making an app based on events during a football match. So I've set up a Player class, and one of the properties is Nationality eg: Scotland. Then I have a DataTemplate, but rather than the string "Scotland" showing up, I would like an image of the national flag to show up instead. All my images are in Images/Countries then are named Scotland.png etc...

The line of code in my data template which I need the binding is:

<Image x:Name="Player_Nationality_Image" Margin="0,0,0,0" Grid.Column="4"Source="Images/Countries/Scotland.png" Height="14" Width="14"/>

Is there an easy way to change my class slightly and bind the image source based on this Nationality property alone? Do I need something in between to convert this?

Here is my Player.vb class:

Imports System.Collections.ObjectModel
Imports System.ComponentModel

Public Class Player
Implements INotifyPropertyChanged

Private playerFirstNameValue As String
Private playerSurnameValue As String
Private playerShirtNameValue As String
Private playerSquadNumberValue As Integer
Private playerDOBValue As Date
Private playerPlaceOfBirthValue As String
Private playerNationalityValue As String

Private playerCategoryValue As Position
Private specialFeaturesValue As SpecialFeatures

Private teamValue As ObservableCollection(Of Team)

Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged



Public Property FirstName() As String
    Get
        Return Me.playerFirstNameValue
    End Get
    Set(ByVal value As String)
        Me.playerFirstNameValue = value
        OnPropertyChanged("FirstName")
    End Set
End Property

Public Property Surname() As String
    Get
        Return Me.playerSurnameValue
    End Get
    Set(ByVal value As String)
        Me.playerSurnameValue = value
        OnPropertyChanged("Surname")
    End Set
End Property

Public Property ShirtName() As String
    Get
        Return Me.playerShirtNameValue
    End Get
    Set(ByVal value As String)
        Me.playerShirtNameValue = value
        OnPropertyChanged("ShirtName")
    End Set
End Property

Public Property SquadNumber() As Integer
    Get
        Return Me.playerSquadNumberValue
    End Get
    Set(ByVal value As Integer)
        Me.playerSquadNumberValue = value
        OnPropertyChanged("SquadNumber")
    End Set
End Property

Public Property StartDate() As Date
    Get
        Return Me.playerDOBValue
    End Get
    Set(ByVal value As Date)
        Me.playerDOBValue = value
        OnPropertyChanged("DateofBirth")
    End Set
End Property

Public Property PlaceOfBirth() As String
    Get
        Return Me.playerPlaceOfBirthValue
    End Get
    Set(ByVal value As String)
        Me.playerPlaceOfBirthValue = value
        OnPropertyChanged("Surname")
    End Set
End Property

Public Property Nationality() As String
    Get
        Return Me.playerNationalityValue
    End Get
    Set(ByVal value As String)
        Me.playerNationalityValue = value
        OnPropertyChanged("Nationality")
    End Set
End Property

Public Property Position() As Position
    Get
        Return Me.playerCategoryValue
    End Get
    Set(ByVal value As Position)
        Me.playerCategoryValue = value
        OnPropertyChanged("Position")
    End Set
End Property


Public Property SpecialFeatures() As SpecialFeatures
    Get
        Return Me.specialFeaturesValue
    End Get
    Set(ByVal value As SpecialFeatures)
        Me.specialFeaturesValue = value
        OnPropertyChanged("SpecialFeatures")
    End Set
End Property

Public ReadOnly Property Team() As ReadOnlyObservableCollection(Of Team)
    Get
        Return New ReadOnlyObservableCollection(Of Team)(Me.teamValue)
    End Get
End Property


Public Sub New(ByVal FirstName As String, ByVal Surname As String, ByVal ShirtName As String, ByVal PlaceOfBirth As String, ByVal NationalityImageSourceString As String, ByVal Category As Position, ByVal squadNumber As Integer, ByVal DOB As Date, ByVal specialFeatures As SpecialFeatures)
    Me.playerFirstNameValue = FirstName
    Me.playerSurnameValue = Surname
    Me.playerShirtNameValue = ShirtName
    Me.playerPlaceOfBirthValue = PlaceOfBirth
    Me.playerNationalityValue = Nationality
    Me.playerDOBValue = DOB
    Me.playerSquadNumberValue = squadNumber


    Me.playerCategoryValue = Category
    Me.specialFeaturesValue = specialFeatures
    Me.teamValue = New ObservableCollection(Of Team)()
End Sub

Protected Sub OnPropertyChanged(ByVal name As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Sub
End Class

Public Enum Position
    GK
    DF
    MF
    FW
End Enum

Public Enum SpecialFeatures
    None
    Yellow
    Red
    SubbedOff
    SubbedOn
    Highlight
End Enum

Data Template in Application.xaml:

<DataTemplate DataType="{x:Type src:Player}">

        <Button Name="Player_Button" Style="{StaticResource Player}" Height="24" Width="320" Margin="0,2,0,0">
            <Grid HorizontalAlignment="Center" Width="300">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="20"></ColumnDefinition>
                    <ColumnDefinition Width="210"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="30"></ColumnDefinition>
                    <ColumnDefinition Width="30"></ColumnDefinition>

                </Grid.ColumnDefinitions>

                <TextBlock Name="Player_Number_Text" Grid.Column="0" FontFamily="Font/#Gotham Narrow Bold" Text="{Binding Path=SquadNumber}" Margin="0,0,0,0" HorizontalAlignment="Left" />
                <StackPanel Orientation="Horizontal" Grid.Column="1">
                    <TextBlock Name="Player_FirstName_Text" FontFamily="Font/#Gotham Narrow Bold" Text="{Binding Path=FirstName}" Margin="5,0,0,0" HorizontalAlignment="Left" />
                    <TextBlock Name="Player_Surname_Text" FontFamily="Font/#Gotham Narrow Bold" Text="{Binding Path=Surname}" Margin="5,0,0,0" HorizontalAlignment="Left" />
                </StackPanel>                   
                <Rectangle Name="Player_Card" Grid.Column="2"></Rectangle>
                <TextBlock Name="Player_Position_Text" Grid.Column="3" FontFamily="Font/#Gotham Narrow Bold" Text="{Binding Path=Position}" Margin="5,0,0,0" />
                <Image x:Name="Player_Nationality_Image" Margin="0,0,0,0" Grid.Column="4" Source="Images/Countries/Scotland.png" Height="14" Width="14" />

            </Grid>
        </Button>



        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=SpecialFeatures}">
                <DataTrigger.Value>
                    <src:SpecialFeatures>Yellow</src:SpecialFeatures>
                </DataTrigger.Value>
                <DataTrigger.Setters>

                    <Setter Property="Fill" Value="Yellow" TargetName="Player_Card" />


                </DataTrigger.Setters>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=SpecialFeatures}">
                <DataTrigger.Value>
                    <src:SpecialFeatures>Highlight</src:SpecialFeatures>
                </DataTrigger.Value>

                <Setter Property="Fill" Value="Blue" TargetName="Player_Card" />

            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>
rwmck
  • 25
  • 2
  • 8
  • Couldn't your player class just expose a property that returns an ImageSource? Player would be responsible for returning the correct image. – PatFromCanada May 03 '13 at 19:11
  • Yes, but I'm unsure how. Especially as it should be as simple as adding the path and .png to whatever Nationality. I've tried a few things, but I keep getting 'Cannot convert String to ImageSource' errors when I try and add a New test Player. – rwmck May 04 '13 at 06:36

1 Answers1

0

You'll need to implement an IValueConverter.

Somewhere in your solution add the following class. (I highly recommend making a converter folder and dumping all converters to be used throughout the application in this folder so you can find and modify them easily down the track.)

Imports System.ComponentModel
Imports System.Windows.Data
Imports System.Windows.Media

Public Class StringToImageConverter
    Implements IValueConverter

    Public Sub New()
    End Sub

    Public Function Convert(value As Object, targetType As Type, parameter As Object,        culture As System.Globalization.CultureInfo) As Object _
    Implements IValueConverter.Convert

             Select Case value
            Case "Scotland"
                '
                Return New ImageSourceConverter().ConvertFromString("/YOURSOLUTION;component/Images/Countries/Scotland.png")
                '
           Case "Australia"
                '
                Return New ImageSourceConverter().ConvertFromString("/YOURSOLUTION;component/Images/Countries/Australia.png")
                '
        Case Else
                Return Nothing
        End Select

    End Function


    Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object _
    Implements IValueConverter.ConvertBack

    End Function
End Class

In Application.xaml place the following code.

 <Form.Resources>
        <my:StringToImageConverter x:Key="StringToImageConverter" />
  <Form.Resources>

 <Button Name="Player_Button" Style="{StaticResource Player}" Height="24" Width="320" Margin="0,2,0,0">
            <Grid HorizontalAlignment="Center" Width="300">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="20"></ColumnDefinition>
                    <ColumnDefinition Width="210"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="30"></ColumnDefinition>
                    <ColumnDefinition Width="30"></ColumnDefinition>

                </Grid.ColumnDefinitions>

                <TextBlock Name="Player_Number_Text" Grid.Column="0" FontFamily="Font/#Gotham Narrow Bold" Text="{Binding Path=SquadNumber}" Margin="0,0,0,0" HorizontalAlignment="Left" />
                <StackPanel Orientation="Horizontal" Grid.Column="1">
                    <TextBlock Name="Player_FirstName_Text" FontFamily="Font/#Gotham Narrow Bold" Text="{Binding Path=FirstName}" Margin="5,0,0,0" HorizontalAlignment="Left" />
                    <TextBlock Name="Player_Surname_Text" FontFamily="Font/#Gotham Narrow Bold" Text="{Binding Path=Surname}" Margin="5,0,0,0" HorizontalAlignment="Left" />
                </StackPanel>                   
                <Rectangle Name="Player_Card" Grid.Column="2"></Rectangle>
                <TextBlock Name="Player_Position_Text" Grid.Column="3" FontFamily="Font/#Gotham Narrow Bold" Text="{Binding Path=Position}" Margin="5,0,0,0" />
        <Image Source="{Binding Path=Nationality, Converter={StaticResource StringToImageConverter}}" Stretch="None" />

            </Grid>

Hope this helps.

freschx
  • 94
  • 1
  • 1
  • 11
  • Could I do this a bit more dynamically? Return New ImageSourceConverter().ConvertFromString("/YOURSOLUTION;component/Images/Countries/" & value & ".png") – rwmck May 09 '13 at 11:26