我正在尝试使用多个小型编辑器来创建WPF应用程序。这些编辑器之一需要加载两个图像,在TextBox中输入名称,然后单击保存按钮。
在代码中,这确实可以正常工作。文件将保存在模型中,并且可以加载图像。在点击保存按钮之前,两个图像实际上都显示在编辑器中。但是,重新打开(用于编辑)后,仅渲染一张图像。
我进行了一些测试,发现总是第一个图像无法渲染,而第二个图像却无法渲染。
例如在XAML中,它看起来像这样:
<Image Name="BackgroundImage" Grid.Row="1" Grid.Column="0" Source="{Binding Path=Background}" Width="120" Height="90"/>
<Image Name="ForegroundImage" Grid.Row="2" Grid.Column="0" Source="{Binding Path=Foreground}" Width="120" Height="90"/>
即使模型的属性 Background 已成功加载图像,也不会渲染 BackgroundImage 。如果我要交换这些XAML标签,这意味着将 ForegroundImage 控件放在 BackgroundImage 上方,则 ForegroundImage 不会被渲染BackgroundImage 可以。即使我不更改其他任何东西,例如Grid.Row或Column。
然后,我尝试在窗口的Loaded事件处理程序中的代码后面加载图像:
private void LocationEditor_OnLoaded(object sender, RoutedEventArgs e)
{
BackgroundImage.Source = ((Location)DataContext).Background;
ForegroundImage.Source = ((Location)DataContext).Foreground;
}
同样适用于这种情况。无论哪一条线首先执行,都不会在Window中呈现。
以防万一,这是 Background 属性的代码( Foreground 的构建方式相同)
[JsonIgnore]
public BitmapImage Background
{
get
{
if (!string.IsNullOrWhiteSpace(BackgroundFile))
{
SetFree();
SetImage();
}
else
_background = null;
return _background;
}
}
SetFree()方法释放了不再需要该图像的内存资源。当窗口关闭或需要 BitmapImage 时,就会发生这种情况。 (如果图片文件已更改,则每次都会重新加载图片。)
SetImage()方法只做一件简单的事情:加载 BackgroundFile 图像文件的图像并将其保存在 _background 字段中
我不太清楚问题可能是什么。我已经尝试了一些方法,但是在编码时我并不经常使用图像。
答案 0 :(得分:1)
您的SetFree()
或SetImage()
方法一定存在问题。
幸运的是,您不需要在视图模型中使用Background
和Foreground
属性,因为WPF提供了string
,Uri
的内置自动类型转换功能和byte[]
至ImageSource
。因此,您可以在视图模型中直接将Image的Source属性绑定到适当的路径属性:
<Image ... Source="{Binding BackgroundFile}"/>
<Image ... Source="{Binding ForegroundFile}"/>
为了完整起见,如果您仍然希望拥有这些属性,我建议使用如下所示的简单实现。内置的图像缓存将确保文件的解码不会比需要的频繁:
public ImageSource Background
{
get
{
if (BackgroundFile != null)
{
try
{
return new BitmapImage(new Uri(BackgroundFile));
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
return null;
}
}
答案 1 :(得分:-1)
绑定问题可能很难解决。有时,评估绑定的时机不明显或似乎没有道理。我知道这是一个通用答案,但是我使用的一个技巧是为我遇到麻烦的绑定添加一个“调试转换器”,以便可以在评估期间进行调试。它救了我几次。
<UserControl
xmlns:converters="clr-namespace:WhateverYourNamespaceIs.Converters">
<UserControl.Resources>
<converters:DebugConverter x:Key="DebugConverter"/>
</UserControl.Resources>
<Image Name="BackgroundImage" Grid.Row="1" Grid.Column="0" Source="{Binding Path=Background, Converter={StaticResource DebugConverter}" Width="120" Height="90"/>
Here is an example of the converter.
public sealed class DebugConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//Debug.WriteLine("Debug Converter Value:" + value.ToString());
// Since you are working with graphics, maybe just dump the size
Debug.WriteLine("Debug Converter Value:" + value.Length().ToString());
return (value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}