Change displayed image in listbox at runtime
I have a Listbox bound to an Observable collecton that has a different image displayed depending on the data within it like so:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="PersonTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Path=ImagePath}"/>
<TextBlock x:Name="id" Text="{Binding Id}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
I then use it later:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="personListBox" ItemTemplate="{StaticResource PersonTemplate}"
ItemsSource="{Binding PersonCollection}"/>
</Grid>
However this means I have created the ImagePath property as part of the Person which isn't really correct, as it is part of the ViewModel rather than the model. Is it possible to somehow to add a binding into the ViewModel that I can pass the Id into an change the image accordingly?
EDIT: I actually after some playing found a way to do it but I am not sure if it is a sensible approach. I created a ValueConverter and used it to change the value.
public class IdToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int id = (int)value;
string img;
switch (id)
{
case 1: img = @"Resources/Image/image1.png"; break;
case 2: img = @"Resources/Image/image2.png"; break;
default: img = @"Resources/Image/unknown.png"; break;
}
return img;
}
Then this works:
<phone:PhoneApplicationPage.Resources>
<local:IdToImageConverter x:Key="IdImageConverter"/>
<DataTemplate x:Key="PersonTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>开发者_JAVA百科;
<Image Source="{Binding Id,Converter={StaticResource IdImageConverter}}"/>
<TextBlock x:Name="id" Text="{Binding Id}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
This is a common requirement and the most common solution it code a specific IValueConverter
as your edit shows. However since its a common requirement it would be better to create a common chunk of code that could be used to handle this.
See this blog for an example of a common converter implementation (its called StringToObjectConverter
but don't let that put you off).
You could then add a converter to the view:-
<local:StringToObjectConverter x:Key="TypeToImageSource">
<ResourceDictionary>
<BitmapImage UriSource="Resources/Image/image1.png" x:Key="1" />
<BitmapImage UriSource="Resources/Image/image2.png" x:Key="2" />
<BitmapImage UriSource="Resources/Image/unknown.png" x:Key="__default__" />
</ResourceDictionary>
</local:StringToObjectConverter>
I'm not sure I understand your question correctly. Are you saying that ImagePath
is not a property of the PersonCollection
collection, that it belongs to some other collection? If so, you can reference it by specifying the DataContext
as follows:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="PersonTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image DataContext="{Binding ImageCollection}"
Source="{Binding Path=ImagePath}"/>
<TextBlock x:Name="id" Text="{Binding Id}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
EDIT:
Re-reading your question I think you're asking how to bind an image that is selected depending on the Id
property of PersonCollection
. To do that, create a collection called ImageCollection
in your ViewModel, containing the property ImagePath
, which contains a list of images that are created corresponding to the list of Id
s appearing in PersonCollection
and bind it as shown above.
精彩评论