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 ライブ タイルに追加します)。

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 メソッドに渡します。このユーザー コントロールをページに追加し、create image メソッドを呼び出すと、問題なく動作することがわかりました。すべてを適切に整列させるページ上でのレンダリングには何かがあるに違いありません。残念ながら、このアプローチは私の状況では不可能です。これを機能させるためにできるステップはありますか?UpdateLayout();コントロールで動作しません。

4

2 に答える 2

1

XAMLをバックグラウンドでレンダリングするという大きな課題に直面しています。私はこの同じ問題をあちこち走り回ってから、最終的にそれが何であるかを理解しました。さらに悪いことに、それはしばしばうまくいくでしょう!

問題は、画像の読み込み方法です。コントロールを作成すると、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 に答える