7

TextBlock を含む UserControl1 という単純な UserControl があります。

  <UserControl x:Class="WpfApplication2.UserControl1"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
     <Grid>
         <TextBlock Text="{Binding}"/>
     </Grid>
</UserControl>

その新しいインスタンスを初期化し、コードで DataContext を指定しました。ウィンドウが閉じているときに、このコントロールを画像ファイルに描画する必要があります。UserControl は、作成されたファイル内の境界テキストをレンダリングしません。

ここに画像の説明を入力

これはユーザーコントロールを使用した私のコードです:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Closing += MainWindow_Closing;
    }

    void MainWindow_Closing(object sender, CancelEventArgs e)
    {
        UserControl1 uc = new UserControl1();
        uc.DataContext = "hello";
        uc.Height = 100;
        uc.Width = 100;
        uc.Background = Brushes.LightBlue;
        DrawToImage(uc);
    }

    private void DrawToImage(FrameworkElement element)
    {
        element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        element.Arrange(new Rect(element.DesiredSize));

        RenderTargetBitmap bitmap = new RenderTargetBitmap((int)element.Width, (int)element.Height,
                                                           120.0, 120.0, PixelFormats.Pbgra32);
        bitmap.Render(element);

        BitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(bitmap));

        using (Stream s = File.OpenWrite(@"C:\555.png"))
        {
            encoder.Save(s);
        }
    }
}

十分に明確であることを願っています。どんな助けでも大歓迎です。

4

5 に答える 5

6

手動で測定/配置した後、コントロールでレイアウトの更新を強制するのを忘れただけです (バインディングの解決を強制するのに十分ではありません)。

UpdateLayoutを簡単に呼び出すだけで機能します。

private void DrawToImage(FrameworkElement element)
{
    element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    element.Arrange(new Rect(element.DesiredSize));
    element.UpdateLayout();

    RenderTargetBitmap bitmap = new RenderTargetBitmap((int)element.Width, (int)element.Height,
                                                        120.0, 120.0, PixelFormats.Pbgra32);
    bitmap.Render(element);

    BitmapEncoder encoder = new PngBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(bitmap));

    using (Stream s = File.OpenWrite(@"C:\555.png"))
    {
        encoder.Save(s);
    }
}

編集:バインディングがいつ解決されるかについての詳細:リンク

于 2012-12-30T12:42:47.290 に答える
0

私がこれを行う場合、それは機能しますが、これがあなたが望むものであるかどうかはわかりません:

<Window x:Class="DrawImage.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:DrawImage="clr-namespace:DrawImage"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DrawImage:UserControl1 x:Name="uc" Visibility="Hidden"/>
    </Grid>
</Window>

void MainWindow_Closing(object sender, CancelEventArgs e)
{
    uc.DataContext = "hello";
    uc.Height = 100;
    uc.Width = 100;
    uc.Background = Brushes.LightBlue;
    uc.Visibility = Visibility.Visible;
    DrawToImage(uc);
}
于 2012-12-30T10:21:00.207 に答える
0

編集

問題を再現できるようになりました。Window コンストラクターで DataContext を設定すると、機能します。Winndow_Closed イベントで設定すると、まったく同じ結果が得られます。

WPF が実際に UI スレッドでテキストをレンダリングするのに時間がかかるため、回避策はないと思います。WPF が UI スレッドでテキストをレンダリングする前に PNG をレンダリングすると、PNG には表示されません。Closedイベント ハンドラの実行中にウィンドウが破棄されるため、回避策はないようです。一方では、UI スレッドにコントロールをレンダリングさせたい場合に、UI スレッドをブロックしてウィンドウへのイベントが破壊されないようにする方法はありません。

コントロールがレンダリングされたらすぐに画像をレンダリングし、ウィンドウを閉じたときに画像ファイルを保存することをお勧めします。

于 2012-12-30T10:28:07.707 に答える
0

userControl1.Loaded イベントで関数 SaveImage() を呼び出してみてください

于 2012-12-27T17:02:32.640 に答える
0

ブログに記事を投稿しました (アカウントに png 透明度を入れる (背景が黒くなる): FrameworkElement を画像として保存する)

FrameworkElement element = myControl.Content;
// you can set the size as you need.
Size theTargetSize = new Size(1500,2000)
element.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(theTargetSize ));
// to affect the changes in the UI, you must call this method at the end to apply the new changes
element.UpdateLayout();

完全なタラはブログ投稿で見つけることができます。

于 2015-03-02T09:25:48.933 に答える