自制的ImageButton嵌入在UserControl中,嵌入在另一个UserControl中,不显示图像

时间:2011-06-22 18:24:52

标签: wpf user-controls imagebutton

我编写了一个基本的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没有显示其图像。我能找到的唯一区别是:

  1. CarImage在Visual Tree中进一步嵌入。不应该有所作为。

  2. PlateImage的Source类型是BitmapImage,而PlateCloseupImageButton的类型是CachedBitmap。

  3. 非常感谢任何帮助。

1 个答案:

答案 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语句时,一切正常。