将 UserControl 保存为 JPG - 结果被“压扁"; [英] Saving UserControl as a JPG - result is "squished"

查看:23
本文介绍了将 UserControl 保存为 JPG - 结果被“压扁";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在将 UserControl 保存为 JPG 时遇到了一个奇怪的问题.基本上我想要做的是创建一个动态磁贴,我可以使用后台代理(以及从应用程序本身)更新它.

I'm having a strange issue with saving a UserControl as a JPG. Basically what I want to do is create a Live Tile that I can update using a Background Agent (as well as from within the app itself.)

我已按照 这篇博文 非常适合我创建磁贴;我有一个自定义的 UserControl,上面有一些 TextBlocks,它以 JPG 格式保存到 IndependentStorage 中,正如帖子所说.

I've followed the steps in this blog post which work great for when I create the tile; I have a custom UserControl with some TextBlocks on it which gets saved as a JPG into IsolatedStorage, exactly as the post says.

创建磁贴没有问题 - UserControl 呈现出应有的效果.但是,当我尝试更新磁贴时(使用完全相同的方法 - 将新控件另存为 JPG,然后使用该 JPG 作为背景图像),事情就崩溃了.

Creating the tile is no problem - the UserControl is rendered nicely as it should be. However, when I try to update the tile (using the exact same method - saving a new control as a JPG, then using that JPG as the BackgroundImage), things break down.

放置在磁贴上(并保存在隔离存储中)的结果图像如下所示:压扁的磁贴(使用隔离存储资源管理器工具从隔离存储中提取)

The resulting image that gets placed on the tile (and saved in IsolatedStorage) looks like this: squished tile (pulled from IsolatedStorage using the Isolated Storage Explorer Tool)

背景为黑色,所有文本沿着图像的一侧向下延伸(并相互重叠) - 预期结果是背景是手机的强调色,文本在顶部附近水平显示.

The background is black, and all the text runs down the side of the image (and overlaps each other) - the expected result is the background being the phone's accent colour, and the text appearing horizontal near the top.

用于生成和保存图像的代码在这两种情况下完全相同 - 我已将其抽象为返回 StandardTileData 的静态方法.唯一的区别是从哪里调用它:在创建 tile 的工作情况下,它是从主应用程序中的一个页面调用的;在非工作情况下(更新磁贴),它是从只能通过从磁贴本身进行深层链接访问的页面调用的.

The code used to generate and save the image is exactly the same in both instances - I've abstracted it out into a static method that returns StandardTileData. The only difference is where it is called from: in the working case where the tile is created, it's called from a page within the main app; in the non-working case (where the tile is updated), it's called from a page that can only be accessed by deep-linking from the tile itself.

有什么想法吗?我猜想将控件渲染为 JPG 时出了点问题,因为实际图像是这样显示的.

Any thoughts? I'm guessing something's going wrong with the rendering of the Control to a JPG, since the actual image comes out this way.

生成图像的代码片段在这里:

The snippet of code that generates the image is here:

StandardTileData tileData = new StandardTileData();

// Create the Control that we'll render into an image.
TileImage image = new TileImage(textA, textB);
image.Measure(new Size(173, 173));
image.Arrange(new Rect(0, 0, 173, 173));

// Render and save it as a JPG.
WriteableBitmap bitmap = new WriteableBitmap(173, 173);
bitmap.Render(image, null);
bitmap.Invalidate();

IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
String imageFileName = "/Shared/ShellContent/tile" + locName + ".jpg";

using (IsolatedStorageFileStream stream = storage.CreateFile(imageFileName))
{
    bitmap.SaveJpeg(stream, 173, 173, 0, 100);
}

tileData.BackgroundImage = new Uri("isostore:" + imageFileName, UriKind.Absolute);

return tileData;

我尝试转换的控件的 XAML 在这里:

The XAML for the control I'm trying to convert is here:

<UserControl x:Class="Fourcast.TileImage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="173" d:DesignWidth="173" FontStretch="Normal" Height="173" Width="173">

    <Border Background="{StaticResource PhoneAccentBrush}">
        <StackPanel>
            <TextBlock  HorizontalAlignment="Stretch"
              TextWrapping="Wrap" VerticalAlignment="Stretch" Style="{StaticResource PhoneTextLargeStyle}" x:Name="Temperature"></TextBlock>
            <TextBlock x:Name="Condition" HorizontalAlignment="Stretch"
              TextWrapping="Wrap" VerticalAlignment="Stretch" Style="{StaticResource PhoneTextNormalStyle}">
            </TextBlock>
        </StackPanel>
    </Border>
</UserControl>

更新:在对调试器进行一些调查后,似乎对 MeasureArrange 的调用在方法是从更新磁贴的类调用的.但是,在创建图块时,这些调用会按预期运行(控件的 ActualWidth 和 ActualHeight 更改为 173).

Update: after some investigation with the debugger, it appears the calls to Measure and Arrange don't seem to do anything when the method is called from the class that's updating the tile. When the tile is being created, however, these calls function as expected (the ActualWidth and ActualHeight of the control get changed to 173).

推荐答案

不确定这里到底发生了什么,但这是我最终为解决该问题所做的工作.

Not sure what exactly is going on here, but here's what I ended up doing to workaround the issue.

我从尝试呈现控件切换到在代码中定义 StackPanel,向其中添加元素,然后将其呈现为图像.奇怪的是,ArrangeMeasure 方法不会做任何事情,除非另一个元素将它们应用于它,而 UpdateLayout 调用.

I switched from trying to render a Control to defining a StackPanel in code, adding elements to it, then rendering that to an image. Oddly enough, though, the Arrange and Measure methods don't do anything unless another element has had them applied to it, and UpdateLayout called.

完整的结果代码(减去 TextBlock 和写入图像的内容)如下.

The full resulting code (minus the contents of the TextBlocks and writing to an image) is below.

StandardTileData tileData = new 

// None of this actually does anything, but for some reason the StackPanel
// won't render properly without it.
Border image = new Border();
image.Measure(new Size(173, 173));
image.Arrange(new Rect(0, 0, 173, 173));
image.UpdateLayout();
// End of function-less code.

StackPanel stpContent = new StackPanel();      

TextBlock txbTemperature = new TextBlock();
txbTemperature.Text = temperature;
txbTemperature.Style = (Style)Application.Current.Resources["PhoneTextLargeStyle"];
stpContent.Children.Add(txbTemperature);

TextBlock txbCondition = new TextBlock();
txbCondition.Text = condition;
txbCondition.Style = (Style)Application.Current.Resources["PhoneTextNormalStyle"];
stpContent.Children.Add(txbCondition);

stpContent.Measure(new Size(173, 173));
stpContent.Arrange(new Rect(0, 0, 173, 173));

这篇关于将 UserControl 保存为 JPG - 结果被“压扁";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆