在viewmodel中使用BitMapImage属性进行图像绑定不起作用

时间:2015-05-18 13:46:07

标签: c# wpf mvvm-light

WPF编码器,我无法使用ViewModel中的BitMapImage属性(ImageSource)绑定图像源。我在这个属性上实现了INotifyPropertyChanged,我在这个网站上查了几个页面并尝试了解决方案,snoop工具显示属性绑定与资源中图像文件的路径是正确的。但是当我选择它时,我无法在每个列表视图项上看到图像。请查看图像的BindImages功能和xaml。我也尝试将属性移动到myList集合中的实际对象。但我仍然没有在运行时看到图像。 这是代码:

    <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

3 个答案:

答案 0 :(得分:0)

您的TestViewModel类没有实现INotifyPropertyChanged interfrace。 在公共类TestViewModel 之后添加:INotifyPropertyChanged

答案 1 :(得分:0)

查看您希望Converter值的string代码,ImageSource属性应为string类型。即使您已将ImageSource属性设为BitmapImage,您也没有设置它,您正在设置_ imagesource变量,该变量不会向视图发送任何通知。对于通知,您应设置ImageSource属性而不是_ imagesource变量。此外,如果您将ImageSource属性设为BitmapImage,则不需要Converter,您可以使用Source Image属性直接绑定此属性}。

答案 2 :(得分:0)

我终于解决了这个问题。我所要做的就是在Test对象中创建一个ImageString字符串属性,而不是在ViewModel中。我将其设置为字符串.empty,但是当绑定发生时,我为其分配了URI路径。

test.cs中

     /// <summary>
     /// Represents a test validation result.
     /// </summary>
    internal class Test : INotifyPropertyChanged
    {

    private string _imgstring = string.Empty;
    public string ImageString
    {
        get
        {
            return _imgstring;
        }
        set
        {
            _imgstring = value;
            // Call OnPropertyChanged whenever the property is updated
            OnPropertyChanged("ImageString");

        }
    }

  }

TestViewModel.cs

   /// <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()
                    {
                       test.ImageString=@"/TestProject;component/Resources/Testimage.gif"



                    });                            
                }       

             }

         }
     }
}

XAML:

  <Image Width="12" Height="12"  Source="{Binding ImageString}"/>