2

我创建了一个由 aUserControl组成的,Grid其中包含一个Image-control。

<UserControl
    x:Class="Album.AlbumPicture"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Album"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400"
    Width="200"
    Height="200"
    >

    <Grid Width="200" Height="200">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Image Name="AlbumPictureImage" Width="200" Height="200" Grid.Column="0" Grid.Row="0"  />
    </Grid>
</UserControl>

现在,我有一个构造函数,它采用现有的Image(从 a 新创建的Stream)并将 分配Image给我的自定义控件Image

AlbumPicture::AlbumPicture(Windows::UI::Xaml::Controls::Image^ Image){
InitializeComponent();
this->AlbumPictureImage = Image;
this->Height = 200;
this->Width = 200;
this->state = AlbumPictureState::SWIPE;
this->StartingPoint = Point(0,0);
} 

为了确保 myUserControl被附加到布局容器中,我制作了Background白色的Grid,它显示得很好。我还Image直接将其添加到布局容器中,并且显示正确。


现在,当我将构造函数更改为

AlbumPicture::AlbumPicture(Windows::UI::Xaml::Media::ImageSource^ Source){
InitializeComponent();
this->AlbumPictureImage->Source = Source;
this->Height = 200;
this->Width = 200;
this->state = AlbumPictureState::SWIPE;
this->StartingPoint = Point(0,0);
}

一切正常,Image将显示。这里有什么问题?

4

2 回答 2

1

所以我实际上是 C#/Xaml 开发人员,但我认为原因是您将控件的引用设置为新图像,但根本没有更新可视树。您可能只是更改了“this.AlbumPictureImage”对象的引用,而可视化树(即带有父/子引用的 FrameworkElement)保留了旧引用。

当您在第二个示例中将实际图像加载到引用的 Image 对象中时,您根本不会更改(或尝试更改)可视化树,因此会显示控件。

我的看法,如果我是对的,你有两个选择:

  • 更改视觉树本身。在 Image Control 的父级中删除对子级的引用,然后添加新的图像控件。

  • 将树中旧图像控件的图像源设置为树中新图像的图像源。

第一个要困难得多,而且充满危险,尤其是如果其中任何一个是异步的。我很确定 Image 控件知道使用调度程序来设置其图像源,因此应该在此处介绍第二个选项。您肯定不会首先获得这种保护,因此您需要确保编组到 UI 线程(使用调度程序),以防异步线程没有 UI 访问权限。

第二个选项也应该很容易实现。如果这段代码很糟糕或被破坏,我绝对道歉,正如我所说:

AlbumPicture::AlbumPicture(Windows::UI::Xaml::Controls::Image^ Image){
InitializeComponent();
this->AlbumPictureImage->Source = Image::Source
this->Height = 200;
this->Width = 200;
this->state = AlbumPictureState::SWIPE;
this->StartingPoint = Point(0,0);
} 

我不知道两个控件的源是否相同,因此您可能需要以某种方式分离它,或者获取底层流并从流本身创建一个新的 ImageSource 对象。

好编码!

于 2013-05-07T18:23:13.907 回答
1

好吧,让我们假设你有usercontrol这样的:

<UserControl Loaded="UserControl_Loaded_1">
    <Grid>
        <Image x:Name="MyImage" />
    </Grid>
</UserControl>

如您所见,我将使用loaded事件而不是constructor用户控件。但它应该导致相同的实现。

在这种情况下,loaded我想采用一个stream(在这种情况下,我将使用一种BitmapImage类型)并将其设置为现有图像,正如您在上面的问题中所描述的那样:

private void UserControl_Loaded_1(object sender, RoutedEventArgs e)
{
    var _Url = new Uri("ms-appx:///assets/logo.png");
    var _Image = new Image
    {
        Source = new BitmapImage(_Url)
    };
    this.MyImage.Source = _Image.Source;
}

是的,那是 C#,而不是 C++/CX。但我认为这是有道理的。

所以,然后我将我usercontrol的图像source属性的源设置source为我现有image控件的属性。这是一个简单的属性分配。这工作正常。image可以丢弃以前存在的控件。image中的将为您usercontrol显示上一个image控件的图像。

我强烈建议您查看控件的CacheMode属性,image因为如果您不了解它在做什么,它可能会让您陷入循环。以下是元评论所说的:

//     A value that indicates that rendered content should be cached when possible.
//     If you specify a value of CacheMode, rendering operations from RenderTransform
//     and Opacity execute on the graphics processing unit (GPU), if available.
//     The default is null, which does not enable a cached composition mode.

祝你好运。

于 2013-05-08T16:05:55.390 回答