Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Alcuni aspetti dell'inizializzazione di Windows Presentation Foundation (WPF) vengono posticipati ai processi che in genere si basano sul fatto che l'elemento sia connesso all'albero logico o visivo. In questo argomento vengono descritti i passaggi che potrebbero essere necessari per inizializzare un elemento che non è connesso ad alcuna struttura ad albero.
Elementi e albero logico
Quando si crea un'istanza di una classe Windows Presentation Foundation (WPF) nel codice, è necessario tenere presente che diversi aspetti dell'inizializzazione degli oggetti per una classe Windows Presentation Foundation (WPF) non sono deliberatamente una parte del codice che viene eseguito quando si chiama il costruttore della classe. In particolare per una classe di controllo, la maggior parte della rappresentazione visiva di tale controllo non è definita dal costruttore. La rappresentazione visiva viene invece definita dal modello del controllo. Il modello proviene potenzialmente da una varietà di origini, ma la maggior parte dei casi il modello viene ottenuto dagli stili del tema. I modelli sono a legame ritardato; il modello necessario non viene associato al componente in questione finché il componente non è pronto per la disposizione. E il controllo non è pronto per il layout finché non viene associato a un albero logico che si connette a una superficie di rendering alla radice. Si tratta dell'elemento di livello radice che avvia il rendering di tutti i suoi elementi figli, come definito nell'albero logico.
L'albero visivo partecipa anche a questo processo. Anche gli elementi che fanno parte della struttura ad albero visuale tramite i modelli non vengono resi completamente istanziati fino a quando non vengono collegati.
Le conseguenze di questo comportamento sono che alcune operazioni che si basano sulle caratteristiche visive completate di un elemento richiedono passaggi aggiuntivi. Un esempio è se si tenta di ottenere le caratteristiche visive di una classe costruita ma non ancora collegata a un albero. Ad esempio, se si desidera chiamare Render su un RenderTargetBitmap e l'oggetto visivo passato è un elemento non connesso a un albero, quell'elemento non è visivamente completo finché non sono completati ulteriori passaggi di inizializzazione.
Uso di BeginInit e EndInit per inizializzare l'elemento
Varie classi in WPF implementano l'interfaccia ISupportInitialize. Usare i metodi BeginInit e EndInit dell'interfaccia per indicare un'area nel codice contenente i passaggi di inizializzazione, ad esempio l'impostazione dei valori delle proprietà che influiscono sul rendering. Dopo che EndInit viene chiamato nella sequenza, il sistema di layout può elaborare l'elemento e iniziare a cercare uno stile implicito.
Se l'elemento su cui si impostano le proprietà è una classe derivata da FrameworkElement o FrameworkContentElement, è possibile chiamare le versioni di classe di BeginInit e EndInit anziché eseguire il cast a ISupportInitialize.
Codice di esempio
L'esempio seguente è il codice di esempio per un'applicazione console che usa le API di rendering e XamlReader.Load(Stream) di un file XAML libero per illustrare il posizionamento corretto di BeginInit e EndInit intorno ad altre chiamate API che regolano le proprietà che influiscono sul rendering.
L'esempio illustra solo la funzione principale. Le funzioni Rasterize e Save (non visualizzate) sono funzioni di utilità che si occupano dell'elaborazione delle immagini e delle operazioni di I/O.
[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
Vedere anche
.NET Desktop feedback