我编写了一个基本的ImageButton控件,它来自Button。这是Generic.XAML中按钮样式的XAML:
<Style TargetType="{x:Type local:ImageButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ImageButton}">
<Button Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Clip="{TemplateBinding Clip}"
ClipToBounds="{TemplateBinding ClipToBounds}"
FlowDirection="{TemplateBinding FlowDirection}"
Height="{TemplateBinding Height}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Margin}"
MaxHeight="{TemplateBinding MaxHeight}"
MaxWidth="{TemplateBinding MaxWidth}"
MinHeight="{TemplateBinding MinHeight}"
MinWidth="{TemplateBinding MinWidth}"
Opacity="{TemplateBinding Opacity}"
OpacityMask="{TemplateBinding OpacityMask}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
ToolTip="{TemplateBinding ToolTip}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Visibility="{TemplateBinding Visibility}"
Width="{TemplateBinding Width}" >
<Image Name="Image"
HorizontalAlignment="Stretch"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Source="{TemplateBinding Source}"
Stretch="Uniform"
VerticalAlignment="Stretch" />
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
如您所见,模板由一个带有Image控件的按钮组成。以下是该类的代码隐藏:
public partial class ImageButton : Button {
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register( "Source", typeof( ImageSource ), typeof( ImageButton ),
new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.AffectsMeasure |
FrameworkPropertyMetadataOptions.AffectsParentMeasure |
FrameworkPropertyMetadataOptions.AffectsRender ) );
public ImageSource Source {
get { return (ImageSource) GetValue( SourceProperty ); }
set { SetValue( SourceProperty, value ); }
}
public ImageButton() : base() {}
static ImageButton() {
// Tell this control to use our default style property in Generic.xaml
DefaultStyleKeyProperty.OverrideMetadata( typeof( ImageButton ), new FrameworkPropertyMetadata( typeof( ImageButton ) ) );
}
}
我知道这个控件有效,因为我编写了一个测试程序,它从硬盘驱动器加载JPEG,从文件流创建一个BitmapImage对象,并将ImageButton的Source属性设置为新的BitmapImage对象。图像显示&amp;用户可以点击它。
我有一个UserControl,我在其中嵌入了ImageButton的一个实例。这是该控件的XAML。
<UserControl x:Class="CarSystem.CustomControls.Channel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cs="clr-namespace:CarSystem.CustomControls"
mc:Ignorable="d"
d:DesignHeight="211" d:DesignWidth="281">
<Grid>
<cs:ImageButton BorderBrush="Black"
BorderThickness="1"
Click="CarImage_Click"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
x:Name="CarImage"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch" />
<Canvas Name="ChannelCanvas">
<ComboBox Background="{x:Null}"
FontSize="18"
Foreground="Black"
HorizontalContentAlignment="Center"
Margin="5"
MinHeight="25"
Name="CameraPicker"
Panel.ZIndex="1"
SelectionChanged="Picker_SelectionChanged"
VerticalAlignment="Top"
Visibility="Hidden" />
<Rectangle Fill="{x:Null}"
Margin="5"
MinHeight="25"
Name="NameRectangle"
RadiusX="2"
RadiusY="2"
Stroke="Black"
Visibility="Hidden" />
<TextBlock FontSize="18"
Foreground="Black"
MinHeight="25"
Name="CameraName"
Visibility="Hidden" />
</Canvas>
</Grid>
Channel的代码隐藏非常漫长且令人费解,所以我不能包含所有内容。 Channel有一个名为DisplayRead的方法,它接受一个名为“read”的对象,类型为DisplayRead(不同的名称空间),从数据库中读取。该对象包含两个JPEG,存储为字节数组。 DisplayRead中的代码决定在ImageButton中显示哪两个JPEG,然后执行以下代码:
if ( read.OverviewImage != null ) {
OverviewImage = new BitmapImage();
using ( MemoryStream memoryStream = new MemoryStream( read.OverviewImage.ImageBytes ) ) {
OverviewImage.BeginInit();
OverviewImage.StreamSource = memoryStream;
OverviewImage.EndInit();
}
}
DisplayImage中的代码只是将要显示的数据(如上图)存储在CLR属性中。存储这些值后,它使用Channel的Dispatcher对象来调度要运行的UpdateChanel方法,该方法实际上设置属性以显示存储在CLR属性中的数据。以下是UpdateChannel的摘录:
// CarImage is an instance of ImageButton in the Channel control
if ( CarImage != null && OverviewImage != null ) {
CarImage.Source = image;
}
// PlateCloseupImageButton is an instance of ImageButton on the UserControl that is this Channel's parent.
// PlateCloseupImage is another CLR property. It holds a BitmapSource that contains a rectangle taken from
// another JPEG in the Read.
PlateCloseupImageButton.Source = PlateCloseupImage;
从上面的片段中,放入CarImage的Source属性的图像没有显示,但放入PlateCloseupImageButton的图像确实显示。
我已经使用SNOOP来移动可视化树,并且显示了两个ImageButtons的Source属性,但是没有设置CarImage的嵌入Image的source属性,但是设置了PlateCloseupImageButton的Source。但是,我在ImageButton的Source属性中向setter添加了一些代码,以查看Image的source属性是否确实为null。它不是;它被设置为我预期的设置。
这令我感到困惑。我不知道为什么嵌入在Channel中的ImageButton没有显示其图像。我能找到的唯一区别是:
CarImage在Visual Tree中进一步嵌入。不应该有所作为。
PlateImage的Source类型是BitmapImage,而PlateCloseupImageButton的类型是CachedBitmap。
非常感谢任何帮助。
贝
答案 0 :(得分:0)
好的,在我的团队负责人的帮助下,我找到了答案。问题的根源在以下代码中:
if ( read.OverviewImage != null ) {
OverviewImage = new BitmapImage();
using ( MemoryStream memoryStream = new MemoryStream( read.OverviewImage.ImageBytes ) ) {
OverviewImage.BeginInit();
OverviewImage.StreamSource = memoryStream;
OverviewImage.EndInit();
}
}
using语句是问题的原因。在BitmapImage可以从中读取图像之前,using语句关闭了MemoryStream。在显示之前,不会从流中读取BitmapImage的字节。当我删除using语句时,一切正常。
贝