0

我在用户控件中有一个网格:

<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneAccentBrush}">
    <Image 
        x:Name="imgBack"
        Opacity=".25" />
    <Grid VerticalAlignment="Top" HorizontalAlignment="Left">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <!-- Some textblocks -->
</Grid>

图像的网格和源的大小在运行时动态设置:

public void ChangeSizeAndImage(int width, int height, string backImagePath)
{
    // Set the height and width
    LayoutRoot.Width = width;
    LayoutRoot.Height = height;

    // Set the background image
    imgBack.Source = new BitmapImage(new Uri(backImagePath, UriKind.RelativeOrAbsolute));

    this.UpdateLayout();
}

然后我调用一个从 ui 元素生成 jpeg 并将其保存到 IsolatedStorage 的方法(稍后添加到 Windows Phone Live Tile)

public static Uri CreateImageFromUIElement(UIElement element, int width, int height)
{
    // Instance to store the image in
    IsolatedStorageFile userStore = IsolatedStorageFile.GetUserStoreForApplication();

    // Random ID to use for the file name
    string id = Guid.NewGuid().ToString("n");

    // create directory to read/write from
    const string shellContentDirectory = "Shared\\ShellContent";
    userStore.CreateDirectory(shellContentDirectory);

    // Render the UIElement into a writeable bitmap
    WriteableBitmap bitmap = new WriteableBitmap(element, new CompositeTransform());

    // Save the bitmap to a file. This stream must be closed in order to be read later
    string imagePath = shellContentDirectory + "\\" + id + ".jpg";
    using (IsolatedStorageFileStream stream = userStore.OpenFile(imagePath, System.IO.FileMode.Create))
    {
        bitmap.SaveJpeg(stream, width, height, 0, 100);
    }

    // Uri to get us to the image
    Uri imageUri = new Uri("isostore:/" + imagePath.Replace('\\', '/'));
    return imageUri;
}

我能够成功地使用磁贴上的图像,除了我只看到黑色背景的图像,我看不到任何文字。我认为这与 jpeg 和透明 PNG 有关,但是,我在上面的网格上设置了一种颜色的背景,所以我不确定为什么它会被认为是透明的。

编辑 1 我正在以编程方式初始化此用户控件,设置一些属性,并将其传递给 create image 方法。我发现如果我将此用户控件添加到页面,然后使用调用创建图像方法,它工作得很好。一定有一些关于它在页面上呈现的东西,导致所有东西都正确排列。不幸的是,这种方法在我的情况下是不可能的。有什么步骤可以让这个工作吗?UpdateLayout();在控件上不起作用。

4

2 回答 2

1

您遇到了以后台方式呈现 XAML 的巨大挑战。在最终意识到它是什么之前,我在同一个问题上跑来跑去。更糟糕的是,每隔一段时间它就可以正常工作!

问题是图像的加载方式。创建控件时,会创建 Image 元素,并将图像加载/解码启动到另一个线程。与此同时,您的线程继续运行。您将控件渲染到文件并保存它,片刻之后(这是您看不到的部分)图像完成加载,并进行实际渲染。太令人沮丧了!

你不能只是拖延在那里,因为你不知道需要多长时间(而且我不确定它是否会那样工作。你要做的就是将你的工作分成多个部分,并且订阅 Image 上的 ImageOpened 事件。当事件触发时,您可以相信一切正常并保存位图。

在后台代理中,这很棘手,因为您需要推迟调用 NotifyComplete() 直到那时,当然图像可能由于多种原因而无法加载。为了完整起见,您还需要订阅 ImageFailed 事件并处理它!

在 WP8 应用程序中,您应该使用 async/await 模式来简化整个流程。在 WP7 中,您需要自己同步事物。如果您需要,我可以发布一些代码。

我希望我有一个更简单的解决方案给你,但希望这会让你朝着正确的方向前进!

于 2013-02-11T08:22:35.243 回答
0

这对我有用:

UserControl myControl = new UserControl();
myControl.Arrange(new Rect(0, 0, Width, Height));

WriteableBitmap writeable = new WriteableBitmap(Width, Height);
Writeable.Render(Control, null);
writeable.Invalidate();

IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile("/Shared/ShellContent/" + Filename);

System.Windows.Media.Imaging.Extensions.SaveJpeg(writeable, fileStream, Width, Height, 0, 100);
fileStream.Close();

希望这可以帮助。

于 2013-03-29T04:10:04.923 回答