Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Alguns aspectos da inicialização do WPF (Windows Presentation Foundation) são adiados para processos que normalmente dependem desse elemento estar conectado à árvore lógica ou à árvore visual. Este tópico descreve as etapas que podem ser necessárias para inicializar um elemento que não está conectado a nenhuma das árvores.
Elementos e a árvore lógica
Ao criar uma instância de uma classe WPF (Windows Presentation Foundation) em código, você deve estar ciente de que vários aspectos da inicialização de objeto para uma classe do WPF (Windows Presentation Foundation) não fazem parte deliberadamente do código executado ao chamar o construtor de classe. Especialmente para uma classe de controle, a maior parte da representação visual desse controle não é definida pelo construtor. Em vez disso, a representação visual é definida pelo modelo do controle. O modelo potencialmente vem de uma variedade de fontes, mas na maioria das vezes o modelo é obtido de estilos de tema. Os modelos são efetivamente associação tardia; o modelo necessário não será anexado ao controle em questão até que o controle esteja pronto para layout. E o controle não está pronto para layout até ser anexado a uma árvore lógica que se conecta a uma superfície de renderização na raiz. É esse elemento de nível raiz que inicia a renderização de todos os seus elementos filho, conforme definido na árvore lógica.
A árvore visual também participa desse processo. Os elementos que fazem parte da árvore visual por meio dos modelos também não são totalmente instanciados até que estejam conectados.
As consequências desse comportamento são que determinadas operações que dependem das características visuais concluídas de um elemento exigem etapas adicionais. Um exemplo é se você estiver 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ê quiser chamar Render um RenderTargetBitmap e o visual que você está passando for um elemento não conectado a uma árvore, esse elemento não será concluído visualmente até que as etapas adicionais de inicialização sejam concluídas.
Usando BeginInit e EndInit para inicializar o elemento
Várias classes no WPF implementam a ISupportInitialize interface. Você usa os métodos BeginInit e EndInit da interface para denotar uma região em seu código que contém passos de inicialização (como configurar valores das propriedades que afetam a renderização). Depois EndInit de ser chamado na sequência, o sistema de layout pode processar o elemento e começar a procurar um estilo implícito.
Se o elemento no qual você está definindo propriedades for uma classe FrameworkElement ou uma classe derivada de FrameworkContentElement, você poderá chamar as versões de classe de BeginInit e EndInit em vez de converter para ISupportInitialize.
Exemplo de código
O exemplo a seguir é um código de exemplo para um aplicativo de console que usa APIs de renderização e XamlReader.Load(Stream) de um arquivo XAML flexível para ilustrar o posicionamento adequado de BeginInit e EndInit ao redor de outras chamadas de API que ajustam as propriedades que afetam a renderização.
O exemplo ilustra apenas a função principal. As funções Rasterize e Save (não mostradas) são funções de utilitário que cuidam do processamento de imagem e da E/S.
[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");
}
<STAThread>
Shared Sub Main(ByVal args() As String)
Dim e As UIElement
Dim _file As String = Directory.GetCurrentDirectory() & "\starting.xaml"
Using stream As Stream = File.Open(_file, FileMode.Open)
' loading files from current directory, project settings take care of copying the file
Dim pc As New ParserContext()
pc.BaseUri = New Uri(_file, UriKind.Absolute)
e = CType(XamlReader.Load(stream, pc), UIElement)
End Using
Dim paperSize As 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
'
Dim image1 As RenderTargetBitmap = Rasterize(e, paperSize.Width, paperSize.Height, 96, 96)
Save(image1, "render1.png")
Dim b As New Button()
b.BeginInit()
b.Background = Brushes.Blue
b.Height = 200
b.Width = b.Height
b.EndInit()
b.Measure(paperSize)
b.Arrange(New Rect(paperSize))
b.UpdateLayout()
' now render the altered version, with the element built up and initialized
Dim image2 As RenderTargetBitmap = Rasterize(b, paperSize.Width, paperSize.Height, 96, 96)
Save(image2, "render2.png")
End Sub
Consulte também
.NET Desktop feedback