在WPF MVVM中绑定图像

51

我在尝试将图片绑定到我的视图模型中遇到了一些问题。我最终解决了XamlParseException的问题,但是图片没有显示出来。我甚至在视图模型中使用硬编码的方式添加了图片,但仍然没有成功。有人能看出我做错了什么吗?

View:

<Image HorizontalAlignment="Left" Margin="0,0,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Bottom" Grid.Row="8" Width="200"  Grid.ColumnSpan="2" >
<Image.Source>
    <BitmapImage DecodePixelWidth="200" UriSource="{Binding Path=DisplayedImage, Mode=TwoWay}" />
</Image.Source>

视图模型:

 string _DisplayedImagePath = @"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg";//string.Empty;
    int _DisplayedImageIndex;
    BitmapImage _DisplayedImage = null;
    public BitmapImage DisplayedImage
    {
        get
        {
            _DisplayedImage = new BitmapImage();
            if (!string.IsNullOrEmpty(_DisplayedImagePath))
            {
                _Rail1DisplayedImage.BeginInit();
                _Rail1DisplayedImage.CacheOption = BitmapCacheOption.OnLoad;
                _Rail1DisplayedImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
                _Rail1DisplayedImage.UriSource = new Uri(_DisplayedImagePath);
                _Rail1DisplayedImage.DecodePixelWidth = 200;
                _Rail1DisplayedImage.EndInit();
            }
            return _Rail1DisplayedImage;
        }
        set
        {
            _Rail1DisplayedImage = value;
            OnPropertyChanged("DisplayedImage");
        }
    }
3个回答

115

在 WPF 中显示 Image 比其他方式容易得多。尝试这样做:

<Image Source="{Binding DisplayedImagePath}" HorizontalAlignment="Left" 
    Margin="0,0,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Bottom" 
    Grid.Row="8" Width="200"  Grid.ColumnSpan="2" />

而属性可以只是一个字符串

public string DisplayedImage 
{
    get { return @"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg"; }
}

虽然你真的应该将图像添加到位于项目根目录下名为Images的文件夹中,并在Visual Studio的属性窗口中将它们的生成操作(Build Action)设置为资源(Resource)...

但你可以使用以下格式访问它们:

public string DisplayedImage 
{
    get { return "/AssemblyName;component/Images/ImageName.jpg"; }
}

更新 >>>

最后一个提示:如果您发现某个控件无法正常工作,请在搜索引擎中输入“WPF”、“该控件的名称”和“类”,比如这里,您可以输入“WPF图像类”。顶部结果通常为MSDN,如果单击链接,您将了解有关该控件的所有信息,大多数页面还提供代码示例。


更新 2 >>>

如果您按照指向MSDN的链接示例操作仍然无法正常工作,则问题不在于Image控件本身。请尝试使用我建议的string属性,使用以下方法:

<StackPanel>
    <Image Source="{Binding DisplayedImagePath}" />
    <TextBlock Text="{Binding DisplayedImagePath}" />
</StackPanel>

如果您在TextBlock中看不到文件路径,则可能没有将您的DataContext设置为视图模型的实例。如果您可以看到文本,则问题可能出在文件路径上。


更新3 >>>

在.NET 4中,上述Image.Source值将起作用。但是,在.NET 4.5中,微软进行了一些可怕的更改,破坏了许多不同的东西,因此在.NET 4.5中,您需要使用完整的pack路径,如下所示:

<Image Source="pack://application:,,,/AssemblyName;component/Images/image_to_use.png">

有关打包URI的更多信息,请参见Microsoft Docs上的WPF中的打包URI页面。


感谢回复。我尝试了那段代码,在 DisplayedImage 中设置了断点,它确实被访问了,但没有图像显示。 - kurgaan
抱歉,表单上没有显示任何图像。如果我直接在XAML中放置路径,则会显示图像。 - kurgaan
是的,抱歉,我没有仔细看你的属性...其实比那还要简单。看看我的编辑。 - Sheridan
非常抱歉之前没有及时发现这个问题。谢谢你,Sheridan。我在一个选项卡控件上有两个选项卡,它们都使用相同的用户控件,但区别在于绑定方式不同。你最后的更新让我意识到我看错了选项卡,因为绑定没有设置好。感谢你的帮助,你真是太棒了。 - kurgaan
当路径为"C:\folder...\image.jpg"时,它可以正常工作,但我无法让它与"/AppName;component/Images/ImageName.jpg"一起工作。这里有什么诀窍吗? - kurgaan
显示剩余11条评论

8

如果您有一个已经生成并返回Image类型的进程,您可以更改绑定(bind)而不必修改任何其他图像创建代码。

在绑定语句中引用图像的".Source"。

XAML

<Image Name="imgOpenClose" Source="{Binding ImageOpenClose.Source}"/>

视图模型字段

private Image _imageOpenClose;
public Image ImageOpenClose
{
    get
    {
        return _imageOpenClose;
    }
    set
    {
        _imageOpenClose = value;
        OnPropertyChanged();
    }
}

内存泄漏你好..更新示例以正确释放图像... - Walter Verhoeven
@WalterVerhoeven您在谈论哪个示例?这里的代码是一个属性,而不是创建图像的过程。 - Galactic
不要释放你已经拥有的图像,只需更新示例并将其替换为“值”,就可以完美地完成。 - Walter Verhoeven

6

@Sheridan 谢谢。如果我在两端都使用 "DisplayedImagePath" 的示例,就像你展示的那样,它可以使用绝对路径正常工作。

至于相对路径,这是我一直连接相对路径的方法,我首先将子目录(!)和图像文件包含在我的项目中..然后我使用 ~ 字符来表示 bin-path。

    public string DisplayedImagePath
    {
        get { return @"~\..\images\osc.png"; }
    }

这是经过测试的,可以看到下面是我在VS2015中的“解决方案资源管理器”界面。

example of image binding in VS2015)

注意:如果您想要单击事件,请使用图像周围的Button标签

<Button Click="image_Click" Width="128" Height="128"  Grid.Row="2" VerticalAlignment="Top" HorizontalAlignment="Left">
  <Image x:Name="image" Source="{Binding DisplayedImagePath}" Margin="0,0,0,0" />
</Button>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接