Fellow WPF coders, I am not unable to bind the source of an image using a BitMapImage property( ImageSource) in the ViewModel. I implemented INotifyPropertyChanged on this property, I looked up several pages on this website and tried the solutions, The snoop tool shows that the property binding was correct with the path to the image file in resources. But I can't see the image on each list view item when I select it. Please take a look at the BindImages Function and the xaml for the image . I also tried moving the property to the the actual object in the myList collection. But I still don't see the image at run time. Here is the code:
<Window x:Class="TestProject.View.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:me="clr-namespace:TestProject.Model"
xmlns:local="clr-namespace:TestProject.Framework.Converter"
xmlns:view="clr-namespace:TestProject.View"
xmlns:viewmodel="clr-namespace:TestProject.ViewModel"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
DataContext="{Binding Test, Source={StaticResource Locator}}"
Title="Test Overview" Height="300" Width="500" Icon="/TestProject;component/Resources/TestProject.png" Background="{StaticResource {x:Static SystemColors.ControlBrushKey}}" WindowStartupLocation="CenterScreen">
<Window.Resources>
<local:ImageConverter x:Key="imageConverter"/>
</Window.Resources>
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="220" />
</Grid.ColumnDefinitions>
<Menu Grid.ColumnSpan="3">
<MenuItem Header="File">
<MenuItem Header="Close" />
</MenuItem>
<MenuItem Header="Edit">
<MenuItem Header="Select" Command ="{Binding SelectCmd}" IsEnabled="{Binding Path=SelectedIndex, ElementName=listView, Converter={StaticResource ResourceKey=enableConverter}}"
ToolTip="Selects the test so the results are displayed in the main window for quick reference." >
<MenuItem.Icon>
<Image Source="/TestProject;component/Resources/Testimage.gif" Height="16" Width="16" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
<ListView Name="listView" ItemsSource="{Binding Source={myList}}" SelectedItem="{Binding SelectedTest, Mode=TwoWay}" SelectionMode="Single" Grid.RowSpan="2" Grid.Row="1" >
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Select" Name="menuSelect" Command ="{Binding SelectCmd}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu},
Path=PlacementTarget.DataContext}"
ToolTip="Selects the test so the results are displayed in the main window for quick reference.">
<MenuItem.Icon>
<Image Source="/TestProject;component/Resources/Testimage.gif" Height="16" Width="16" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListView.ContextMenu>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Width="12" Height="12" Source="{Binding ImageSource}" DataContext="{Binding Test, Source={StaticResource Locator}}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
ImageConverter.cs
public sealed class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
try
{
return new BitmapImage(new Uri((string)value));
}
catch
{
return new BitmapImage();
}
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
TestViewmodel.cs
public class TestViewModel
{
#region Fields
private BitmapImage _imagesource;
#endregion
#region Properties
public BitmapImage ImageSource
{
get
{
return _imagesource;
}
set
{
_imagesource = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("ImageSource");
}
}
#endregion
#region Relay Commands
/// <summary>
/// Command that selects the test in the list of the tests.
/// </summary>
public RelayCommand SelectCmd { get; private set; }
/// <summary>
/// Command to select the tested subdivision from the context menu of the list view
/// </summary>
public RelayCommand<MenuClass> ContextSelectCmd { get; private set; }
#endregion
public TestViewModel()
{
_imagesource = new BitmapImage();
TestProject.Instance.PropertyChanged += TestProject_SelectedChange_Changed;
ContextSelectCmd = new RelayCommand<MenuClass>(SelectMenuItem);
SelectCmd = new RelayCommand(() => SelectTest(), () => true);
}
private void TestProject_SelectedChange_Changed(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
try
{
if (e.PropertyName == "SelectedTest")
{
//Select the selected item.
Dispatcher.CurrentDispatcher.DynamicInvoke(BindImages);
}
}
catch (Exception ex)
{
ErrorLogger.Log(LogLevel.Error, ex.ToString());
}
}
/// <summary>
/// Sets the selection checkmarks.
/// </summary>
public void BindImages()
{
List<Test> myTests= new List<Test>();
foreach (var item in TestProject.Instance.TestHistory.Values)
{
myTests = item;
foreach (Test test in myTests)
{
if (TestProject.Instance.SelectedTest.ContainsKey(test.Order.Id))
{
if (TestProject.Instance.SelectedTest[test.Order.Id] == test)
{
Dispatcher.CurrentDispatcher.DynamicInvoke(delegate()
{
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri(@"/TestProject;component/Resources/Testimage.gif", UriKind.Relative);
logo.EndInit();
Imagesource = logo;
});
}
}
}
}
}
private void SelectMenuItem ( MenuClass m )
{
try
{
Test t = SelectedTest as Test;
if (t != null)
{
Test tst = t;
if (TestProject.Instance.SelectedTest.ContainsKey(tst.Order.Id))
{
TestProject.Instance.SelectedTest[tst.Order.Id] = tst;
}
else
{
TestProject.Instance.SelectedTest.Add(tst.Order.Id, tst);
}
TestProject.Instance.OnPropertyChanged("SelectedTest");
}
}
catch (Exception ex)
{
ErrorLogger.Log(LogLevel.Error, ex.ToString());
}
}
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Safely raises the PropertyChanged event.
/// </summary>
/// <param name="property">The property name.</param>
protected void OnPropertyChanged(string Status)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(Status));
}
}
#endregion