How do I bind to a validation rule in XAML - validation

I am following the example given here:
https://social.technet.microsoft.com/wiki/contents/articles/31422.wpf-passing-a-data-bound-value-to-a-validation-rule.aspx
I get the exception at the following line in my DataTemplateSelector:
return element.FindResource("MinParameterDataTemplateThin") as DataTemplate;
"Unexpected record in Baml stream. Trying to add to MaximumValueValidation which is not a collection or has a TypeConverter."
Code:
public class BindingProxy : System.Windows.Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
public object Data
{
get => (object)GetValue(DataProperty);
set => SetValue(DataProperty, value);
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new PropertyMetadata(null));
}
public class MaxValueWrapper : DependencyObject
{
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(double),
typeof(MaxValueWrapper), new FrameworkPropertyMetadata(double.MaxValue));
public int MaxValue
{
get => (int)GetValue(MaxValueProperty);
set => SetValue(MaxValueProperty, value);
}
}
public class MaximumValueValidation : ValidationRule
{
public MaxValueWrapper MaxValueWrapper { get; set; }
/// <summary>
/// validate whether the input value is in range
/// </summary>
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
try
{
if (value != null && ((string)value).Length > 0)
{
double userInput = double.Parse((string)value);
if (userInput > MaxValueWrapper.MaxValue)
return new ValidationResult(false,
"Please enter a value <= Max " + MaxValueWrapper.MaxValue);
}
}
catch (Exception e)
{
return new ValidationResult(false, $"Invalid characters or {e.Message}");
}
return ValidationResult.ValidResult;
}
}
XAML:
<DataTemplate x:Key="MinParameterDataTemplateThin">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="120"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding DisplayName, StringFormat='{}{0}:'}" Grid.Column="0" Margin="10,5,5,10" VerticalAlignment="Top" TextWrapping="Wrap"
Visibility="{Binding Visibility}" ToolTipService.ShowDuration="20000">
<TextBlock.ToolTip>
<ToolTip DataContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={x:Static RelativeSource.Self}}">
<TextBlock Text="{Binding Description}"/>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBox Margin="5" Width="50" VerticalAlignment="Top"
Visibility="{Binding Visibility}" IsEnabled="{Binding IsEnabled}">
<i:Interaction.Behaviors>
<utilities:SelectTextOfTextBox/>
</i:Interaction.Behaviors>
<TextBox.Resources>
<validations:BindingProxy x:Key="proxy" Data="{Binding}"/>
</TextBox.Resources>
<TextBox.Text>
<Binding Path="{Binding DefaultValue, StringFormat=N2}" Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnExceptions="True"
NotifyOnValidationError="True"
ValidatesOnNotifyDataErrors="True">
<Binding.ValidationRules>
<validations:MaximumValueValidation ValidatesOnTargetUpdated="True">
<validations:MaximumValueValidation.MaxValueWrapper>
<validations:MaxValueWrapper MaxValue="{Binding Data.MaxValue, Source={StaticResource proxy}}"/>
</validations:MaximumValueValidation.MaxValueWrapper>
</validations:MaximumValueValidation>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock Text="{Binding UnitSymbol}" Margin="5" VerticalAlignment="Top" Visibility="{Binding Visibility}"/>
</StackPanel>
</Grid>
</DataTemplate>
I have several working DataTemplates like this one, but they do not use validation rules with the TextBox. Perhaps I am not following the wiki example correctly, but I am not seeing the problem, and I don't understand the exception.
EDIT:
After staring at the exception message, it occurs to me that the "outer" DataTemplate might be relevant, but I cannot be sure. The DataTemplate above is for a WorkflowParameter object, which is part of a Collection nested in a parent WorkflowParameter object. The DataTemplate for this parent is:
<DataTemplate x:Key="GroupedInversionParameterDataTemplate">
<Grid Visibility="{Binding Visibility}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160"/>
<ColumnDefinition Width="800"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding DisplayName, StringFormat='{}{0}:'}" Grid.Column="0" Margin="5" VerticalAlignment="Top" TextWrapping="Wrap"
Visibility="{Binding Visibility}" ToolTipService.ShowDuration="20000">
<TextBlock.ToolTip>
<ToolTip DataContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={x:Static RelativeSource.Self}}">
<TextBlock Text="{Binding Description}"/>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
<ItemsControl ItemsSource="{Binding GroupedWorkflowParameters}" Grid.Column="1"
ItemTemplateSelector="{StaticResource WorkflowParameterTemplateSelector}"
IsTabStop="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Visibility" Value="{Binding Visibility}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
</DataTemplate>
The mention of trying to add a collection, in the exception message, made me think that the ItemsControl in this outer template could be a problem. I would not expect it to be an issue, but maybe I am missing something.

I though the problem as with the validation XAML, so I commented it out and found there was still an exception. This snippet of XAML:
<Binding Path="{Binding DefaultValue, StringFormat=N2}"
had to change to
<Binding Path="DefaultValue" StringFormat="N2"

Related

Change item control property of checked listview item Xamarin.Forms

Hy,
I am trying to show a comment input if the item checkbox is checked and hide it else, i have this XAML
<ListView ItemsSource="{Binding TaskItems}" x:Name="TasksItems" HasUnevenRows="True" VerticalScrollBarVisibility="Default" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout IsVisible="True" Orientation="Vertical">
<Grid BackgroundColor="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<StackLayout Grid.Column="0" Grid.Row="0">
<input:CheckBox Type="Box" IsChecked="{Binding TaskChecked , Mode=TwoWay}"/>
</StackLayout>
<StackLayout Grid.Column="0" Grid.Row="1" IsVisible="{Binding CommentRequired}">
<Entry BackgroundColor="White" PlaceholderColor="Black" HeightRequest="40" TextColor="Black"/>
</StackLayout>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
and i have this c# code to read the items from database
public class TaskData
{
public bool TaskChecked { get; set; }
public bool CommentRequired { get; set; }
}
public partial class HomePage : ContentPage
{
public HomePage()
{
ObservableCollection<TaskData> TaskItems { get; set; }
ObservableCollection<TaskData> TasksList;
TaskItems = new ObservableCollection<TaskData>();
//Loop the tasks from database result
While...
TaskItems.Add(new TaskData
{
TaskChecked = false,
CommentRequired = false,
});
//End Loop
TasksListView.ItemsSource = TaskItems;
}
}
Now i need to add a "CheckChanged" event to show the comment Entry (IsVisible="True") when the user check the checkbox of the targed listview item
Thanks
First add the event.
<input:CheckBox Type="Box" IsChecked="{Binding TaskChecked , Mode=TwoWay}" CheckedChanged="OnCheckBoxCheckedChanged"/>
Add Name for the second stack
<StackLayout x:Name="StackLayoutEntry" Grid.Column="0" Grid.Row="1" IsVisible="{Binding CommentRequired}">
<Entry BackgroundColor="White" PlaceholderColor="Black" HeightRequest="40" TextColor="Black"/>
</StackLayout>
Then in code Behind use this function to find the entry for the clicked checkbox
void OnCheckBoxCheckedChanged(object sender, CheckedChangedEventArgs e)
{
var Sender = (CheckBox)sender;
var stacklayoutentry = Sender.Parent.FindByName<StackLayout>("StackLayoutEntry");
stacklayoutentry.IsVisible = True;
}
This might also help you also Check
Another approach but you an identifier to your selected item.
Check

ListView Xamarin.forms dynamically load image from ItemSource with ImageResource

I have an issue in my xamarin.Forms application in MVVM. I have a ListView and I want to show an image in the ItemTemplate. To do that I have created a ImageRessource Class:
[ContentProperty("Source")]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
{
return null;
}
var imageSource = ImageSource.FromResource($"CoPro.Assets.{Source}");
return imageSource;
}
}
Here is the xaml of my ListView:
<ListView ItemsSource="{Binding Series}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackLayout Orientation="Horizontal">
<Image Source="{images:ImageResource image.jpg}"/>
</StackLayout>
<Label Grid.Column="1" Text="{Binding Name}" Style="{StaticResource UsualLabelTemplate}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Besides, I have set "images" by this namespace :xmlns:images="clr-namespace:CoPro.Assets"
Like this, my ListView show the same picture for every "Series" Item.
For each Item there is a string property with the path of the image.
How can I show image of each Item, please?
Thanks in advance for your help.
I have just found the solution. I had to use Source property from Image tag:
<ListView Grid.Row="1" x:Name="MainListView" ItemsSource="{Binding Series}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding ImageUrl, Converter={StaticResource StringToImageSourceConverter}}"
Aspect="AspectFill"
/>
<Label Grid.Column="1" Text="{Binding Name}" Style="{StaticResource UsualLabelTemplate}" />
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The solution was to use a Converter, and Source property contained a string. This string is sent into parameter in my converter like this:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
return ImageSource.FromResource($"CoPro.Assets.{value}");
}
else
{
return null;
}
}
in this code "$"CoPro.Assets" is the path where is my image File.
Thanks for your help

Windows Phone 7 MVVM databinding form

I'm new to Windows Phone development, and currently have a simple form. I'm using the MVVM pattern and MvvmLight to run a command. The "Applicant" entity is always empty, and it looks like the 2 way databinding isn't working. Here is my code, I hope someone can point me in the right direction.
View
<Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{Binding Applicant}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="create account" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<StackPanel>
<TextBlock FontSize="15" TextWrapping="Wrap" Margin="0,0,0,10" Text="Please register to create your applicant account. No information will be passed to third parties for any reason."></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="Forename" Width="100"></TextBlock>
<TextBox Width="350" BorderBrush="Red" DataContext="{Binding Forename, Mode=TwoWay}"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="Surname" Width="100"></TextBlock>
<TextBox Width="350" x:Name="Surname" BorderBrush="Red" DataContext="{Binding Surname, Mode=TwoWay}"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="Email" Width="100"></TextBlock>
<TextBox Width="350" x:Name="EmailAddress" BorderBrush="Red" DataContext="{Binding EmailAddress, Mode=TwoWay}"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="Password" Width="100"></TextBlock>
<PasswordBox Width="350" x:Name="PassPhrase" BorderBrush="Red" DataContext="{Binding PassPhrase, Mode=TwoWay}"></PasswordBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="City" Width="100"></TextBlock>
<TextBox Width="350" x:Name="City" DataContext="{Binding City, Mode=TwoWay}"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="State" Width="100"></TextBlock>
<TextBox Width="350" x:Name="County" DataContext="{Binding County, Mode=TwoWay}"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="Country" Width="100"></TextBlock>
<TextBox Width="350" x:Name="Country" DataContext="{Binding Country, Mode=TwoWay}"></TextBox>
</StackPanel>
<StackPanel>
<Button Name="btnContact"
Content="Register"
DataContext="{Binding ElementName=this, Path=DataContext}"
Command="{Binding SaveApplicantCommand}"
Width="300"/>
</StackPanel>
</StackPanel>
</Grid>
</Grid>
View code behind
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ApplicantViewModel vm = new ApplicantViewModel();
DataContext = vm;
}
View Model (the view model inherits from ViewModelBase which implements INotifyPropertyChanged)
public class ApplicantViewModel : ViewModelBase
{
public ApplicantViewModel()
{
SaveApplicantCommand = new RelayCommand(SaveApplicant);
Applicant = new Applicant();
}
public ICommand SaveApplicantCommand {get; set;}
void SaveApplicant()
{
if (string.IsNullOrEmpty(Applicant.Forename))
{
MessageBox.Show("Please enter a forename", "Oops...", MessageBoxButton.OK);
return;
}
db.AddObject("Applicants", Applicant);
db.BeginSaveChanges(OnChangesSaved, db);
}
void OnChangesSaved(IAsyncResult result)
{
}
private Applicant _applicant;
public Applicant Applicant
{
get
{
return _applicant;
}
set
{
if (_applicant != value)
{
_applicant = value;
RaisePropertyChanged("Applicant");
}
}
}
}
Whatever is entered into the Forename text box, I always get the error message because Forename is null.
***** UPDATE *********
Here is the Forename property in the model
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Services.Design", "1.0.0")]
public string Forename
{
get
{
return this._Forename;
}
set
{
this.OnForenameChanging(value);
this._Forename = value;
this.OnForenameChanged();
this.OnPropertyChanged("Forename");
}
}
An ApplicantViewModel does not have a Forename property. Only Applicant has. So do the following:
<TextBox Width="350" BorderBrush="Red"
DataContext="{Binding Applicant.Forename, Mode=TwoWay}"/>
do the same with the other text boxes.

Binding list Collection from a list collection in Window Phone 7

How to Binding list Collection from a list collection in Window Phone 7 while i am able to bind from a single list collection
First of all have item template in your Xaml.
Add Binding to it.
Define that binding property in your code.
Assign values to the defined property.
I am having a item template in my Xaml like this :
<Grid.RowDefinitions>
<RowDefinition Height="367*" />
</Grid.RowDefinitions>
<ListBox HorizontalAlignment="Stretch" Name="lstbNewOrders" Grid.Row="1" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="itemTemplate" Background="Transparent" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<TextBlock FontSize="30" Name="txtEbeln" Text="{Binding ebeln}" Grid.Row="0" Grid.Column="0" FontWeight="Bold" />
<TextBlock FontSize="25" Name="txtCName" Text="{Binding cname}" Grid.Row="1" Grid.Column="0" />
<TextBlock FontSize="25" Name="txtDate" Text="{Binding date}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" TextAlignment="Right"/>
<StackPanel Height="30" Name="stkPanel01" HorizontalAlignment="Right" Grid.Row="0" Grid.Column="1">
<TextBlock FontSize="25" Name="txtNetw" Text="{Binding netw}" HorizontalAlignment="Right" TextAlignment="Right"/>
</StackPanel>
<TextBlock FontSize="25" Name="txtVName" Text="{Binding vname}" Grid.Row="2" Grid.Column="0" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
In my code file i will define the binding like this:
public class itemListForListBox
{
public string ebeln { get; set; }
public string cname { get; set; }
public string vname { get; set; }
public string netw { get; set; }
public string date { get; set; }
}
And provide values like this:
void fillList()
{
List<itemListForListBox> itemListbox = new List<itemListForListBox>();
itemListForListBox listItem;
for (int i = 0; i < 5;i++ )
{
listItem = new itemListForListBox();
listItem.ebeln = "Name "+i;
listItem.date = "Date "+i;
listItem.vname = "VName "+i;
listItem.netw = "Amount "+ i;
listItem.cname = "CName "+i;
itemListbox.Add(listItem);
}
lstbNewOrders.ItemsSource = itemListbox;
}
Hope this might help you.
Thanks.
You can use the code below,
<ListBox Name="RouteListBox" ItemContainerStyle="{StaticResource RouteListBoxItemStyle}" SelectedItem="{Binding Model.SelectedRoute,Mode=TwoWay}" ItemsSource="{Binding RouteListCollection}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<command:EventToCommand Command="{Binding RouteItemSelectedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding RouteName}" Style="{StaticResource RoutesStyle}" Grid.Column="1" />
<Border Style="{StaticResource RouteCountBorder}" Visibility="Collapsed" Grid.Column="2">
<TextBlock Style="{StaticResource RoutesCount}" Visibility="Collapsed" Text="{Binding ShopCount,Mode=TwoWay}"></TextBlock>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate></ListBox>
I take it you mean you have a collection of collections? In this case, you can nest your ItemsControls (or ListBox):
<ItemsControl ItemsSource={Binding Path=???}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- here is your nested itemscontrol -->
<ItemsControl ItemsSource={Binding Path=???}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- your content goes here -->
</DataTemplate>
<ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Let say we have a ListBox lstbx and a collection lets say
List <String> listdata = new List<String>();
we can add items to the collection by Add()
Ex-
listdata.Add("Nazi 1");
or
forloop(expression)
{
listdata.Add("vale")
}
then we can assign assign the collection directly to the listbox' item Source
ex.
lstbx.ItemSource=listdata;
//make sure if u are storing more than one variable in a single item of the collection ,you should create custom data template for the ListBox Item Template. !

Windows Phone 7 - Images & Themes in a databound listbox

I have a listbox that I'm doing some databinding. As you can see I have some images associated with the data that I'm displaying... Everything is working great, except that when I change themes I need to change my image to the black images. I can't seem to figure out how to change the images when they are bound like this.
Any ideas?
<ListBox x:Name="lbPharm" ItemsSource="{Binding col}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="DataTemplateStackPanel" Orientation="Horizontal">
<TextBlock FontFamily="Segoe WP Semibold" FontWeight="Bold" FontSize="30" VerticalAlignment="Top" Margin="20,10">*</TextBlock>
<StackPanel>
<TextBlock x:Name="ItemText" Text="{Binding name}" FontSize="{StaticResource PhoneFontSizeLarge}"/>
<TextBlock x:Name="ItemNumber" Text="{Binding number}" FontSize="{StaticResource PhoneFontSizeNormal}"/>
</StackPanel>
<Image Source="Images/phone.png" Margin="20,0" x:Name="phone" Visibility="Visible">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener Tap="GestureListener_Tap_Phone"/>
</toolkit:GestureService.GestureListener>
</Image>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You should create a binding for the image source instead of setting it explicitly in XAML.
<ListBox x:Name="lbPharm" ItemsSource="{Binding col}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="DataTemplateStackPanel" Orientation="Horizontal">
<TextBlock FontFamily="Segoe WP Semibold" FontWeight="Bold" FontSize="30" VerticalAlignment="Top" Margin="20,10">*</TextBlock>
<StackPanel>
<TextBlock x:Name="ItemText" Text="{Binding name}" FontSize="{StaticResource PhoneFontSizeLarge}"/>
<TextBlock x:Name="ItemNumber" Text="{Binding number}" FontSize="{StaticResource PhoneFontSizeNormal}"/>
</StackPanel>
<!-- Image source is bound to a property -->
<Image Source="{Binding ImageSource}" Margin="20,0" x:Name="phone" Visibility="Visible">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener Tap="GestureListener_Tap_Phone"/>
</toolkit:GestureService.GestureListener>
</Image>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now, just update the property in your view model as needed, as long as the class containing the property implements INotifyPropertyChanged the new image will show up in your ListBox.
The ImageSource property may have to be a BitmapImage instead of a string. XAML must use a converter to convert your path string when it is used as a literal but I think it doesn't do this if you use a binding. Or you could use your own converter. Either way, construct a BitmapImage as follows:
new BitmapImage( new Uri( "/path/to/image.png", UriKind.Relative ) )
EDIT
Adding an example:
<DataTemplate x:Key="LongListSelectorItemTemplate">
<StackPanel VerticalAlignment="Top"
Orientation="Horizontal">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener Tap="OnTap" />
</toolkit:GestureService.GestureListener>
<Image Source="{Binding ImageSource}"
MinHeight="32"
MinWidth="32"
MaxHeight="48"
MaxWidth="48" />
<StackPanel>
<TextBlock Text="{Binding Name}"
Style="{StaticResource PhoneTextExtraLargeStyle}"
Margin="12,10,12,0" />
<TextBlock Text="{Binding Parent}"
Foreground="{StaticResource PhoneAccentBrush}"
Style="{StaticResource PhoneTextSubtleStyle}"
Margin="24,0,12,10" />
</StackPanel>
</StackPanel>
</DataTemplate>
Corresponding view model:
public class Item : INotifyPropertyChanged
{
#region Private Members
private string _name = null;
private string _imageSource = null;
private string _parent = null;
#endregion
public string Name
{
get
{
return _name;
}
set
{
if( value != _name ) {
_name = value;
NotifyPropertyChanged( "Name" );
}
}
}
public string Parent
{
get
{
return _parent;
}
set
{
if( value != _parent ) {
_parent = value;
NotifyPropertyChanged( "Parent" );
}
}
}
public string ImageSource
{
get
{
return _imageSource;
}
set
{
if( value != _imageSource ) {
_imageSource = value;
NotifyPropertyChanged( "ImageSource" );
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged( String propertyName )
{
PropertyChangedEventHandler handler = PropertyChanged;
if( null != handler ) {
handler( this, new PropertyChangedEventArgs( propertyName ) );
}
}
#endregion
}
This is code from a project I'm working on, it is similar to your case except I'm displaying the image with a LongListSelector instead of a ListBox. And it looks like I mislead you earlier about not being able to use a string directly for the image source, I'm doing exactly that and it works. Sorry about that.

Resources