Compartilhar via


Inicialização de Elementos de Objeto que não estão numa Árvore de Elementos

Alguns aspectos da inicialização do Windows Presentation Foundation (WPF) são deixadas para processos que geralmente contam com um elemento estar conectado à árvore lógica ou à árvore visual. Este tópico descreve os passos que podem ser necessários para inicializar um elemento que não está conectado a nenhuma árvore.

Este tópico contém as seguintes seções.

  • Elementos e a Árvore Lógica
  • Tópicos relacionados

Elementos e a Árvore Lógica

Quando você cria uma instância de uma classe Windows Presentation Foundation (WPF) em código, você deve estar ciente de que diversos aspectos de inicialização de objeto de uma classe Windows Presentation Foundation (WPF) não são parte do código executado quando o construtor da classe é chamado. Em particular para uma classe de controle, a maior parte da representação visual daquele controle não é definida pelo construtor. Em vez disso, a representação visual é definida pelo modelo do controle. O modelo pode vir de diversas origens, mas mais frequentemente o modelo é obtido de estilos de tema. Modelos são efetivamente de ligação tardia; o modelo necessário não é anexado ao controle em questão até que o controle esteja pronto para o layout. E o controle não está pronto para o layout até que seja anexado a uma arvore lógica que conecta com uma superfície de renderização na raiz. Esse elemento de nível raiz e que inicia a renderização de todos os elementos filhos como definido na árvore lógica.

A árvore visual também participa deste processo. Elementos que são parte da árvore visual através de modelos também não são completamente instanciados até que estejam conectados.

As consequências deste comportamento são que certas operações que contam com as características visuais completas de um elemento requerem passos adicionais. Um exemplo é se você está tentando obter as características visuais de uma classe que foi construída mas ainda não anexada a uma árvore. Por exemplo, se você quer chamar Render em um RenderTargetBitmap e o visual que você está passando é um elemento não conectado a uma árvore, esse elemento não está visualmente completo até que passos de inicialização adicionais sejam completados.

Utilizando BeginInit e EndInit para Inicializar o Elemento

Diversas classes no WPF implementam a interface ISupportInitialize. Você utiliza os métodos BeginInit e EndInit da interface para denotar a região no seu código que contém passos de inicialização (tal como definir valores de propriedades de configuração que afetam a renderização). Depois que EndInit é chamado na sequência, o sistema de layout pode processar o elemento e começar a procurar um estilo implícito.

Se o elemento para o qual você está definindo proprieades for um FrameworkElement ou classe derivada de FrameworkContentElement, então você pode charma as versões de classes de BeginInit e EndInit em vez de enviar para ISupportInitialize,

Código de Exemplo

O exemplo a seguir é um código de exemplo para uma aplicação de console que utiliza APIs de renderização e XamlReader.Load(Stream) de um arquivo avulso XAML para ilustrar o posicionamento adeuqado de BeginInit e EndInit em torno de outras chamadas de API que ajustam propriedades que afetam a renderização.

Esse exemplo ilustra apenas a função principal. As funções Rasterize e Save (não mostradas) são funções utilitárias que cuidam do processamento de imagem e ES.

[STAThread]
static void Main(string[] args)
{
    UIElement e;
    string file = Directory.GetCurrentDirectory() + "\\starting.xaml";
    using (Stream stream = File.Open(file, FileMode.Open))
    {
        // loading files from current directory, project settings take care of copying the file
        ParserContext pc = new ParserContext();
        pc.BaseUri = new Uri(file, UriKind.Absolute);
        e = (UIElement)XamlReader.Load(stream, pc);
    }

    Size paperSize = new Size(8.5 * 96, 11 * 96);
    e.Measure(paperSize);
    e.Arrange(new Rect(paperSize));
    e.UpdateLayout();

    /*
     *   Render effect at normal dpi, indicator is the original RED rectangle
     */
    RenderTargetBitmap image1 = Rasterize(e, paperSize.Width, paperSize.Height, 96, 96);
    Save(image1, "render1.png");

    Button b = new Button();
    b.BeginInit();
    b.Background = Brushes.Blue;
    b.Width = b.Height = 200;
    b.EndInit();
    b.Measure(paperSize);
    b.Arrange(new Rect(paperSize));
    b.UpdateLayout();

    // now render the altered version, with the element built up and initialized

    RenderTargetBitmap image2 = Rasterize(b, paperSize.Width, paperSize.Height, 96, 96);
    Save(image2, "render2.png");
}

Consulte também

Conceitos

Árvores em WPF

Visão Geral sobre Renderização de Gráficos do Windows Presentation Foundation

XAML Overview