2011-08-23 10 views
6

Quando si assegna un oggetto a un controllo contenuto, si materializzerà un'immagine visiva appropriata per quell'oggetto assegnato. Esiste un modo programmatico per ottenere lo stesso risultato? Vorrei chiamare una funzione in WPF con un oggetto e recuperare un Visual, in cui la stessa logica viene applicata per generare il Visual come se avessi fornito l'oggetto a un'istanza di controllo del contenuto.WPF - Come materializzare programmaticamente l'oggetto nel contenuto visivo?

Ad esempio, se si dispone di un oggetto POCO e lo si assegna a un controllo Contenuto e si verifica un DataTemplate appropriato definito, questo modello si materializza per creare il Visual. Vorrei che il mio codice fosse in grado di prendere un oggetto POCO e tornare da WPF al Visual.

Qualche idea?

risposta

8

Utilizzare DataTemplate.LoadContent(). Esempio:

DataTemplate dataTemplate = this.Resources["MyDataTemplate"] as DataTemplate; 
FrameworkElement frameworkElement = dataTemplate.LoadContent() as FrameworkElement; 
frameworkElement.DataContext = myPOCOInstance; 

LayoutRoot.Children.Add(frameworkElement); 

http://msdn.microsoft.com/en-us/library/system.windows.frameworktemplate.loadcontent.aspx

Se si dispone di un DataTemplate definita per tutte le istanze di un tipo (DataType = {x: Tipo ...}, ma non x: Key = "...") quindi è possibile creare contenuto utilizzando il DataTemplate appropriato utilizzando il seguente metodo statico. Questo metodo emula anche ContentControl restituendo un TextBlock se non viene trovato DataTemplate.

/// <summary> 
/// Create content for an object based on a DataType scoped DataTemplate 
/// </summary> 
/// <param name="sourceObject">Object to create the content from</param> 
/// <param name="resourceDictionary">ResourceDictionary to search for the DataTemplate</param> 
/// <returns>Returns the root element of the content</returns> 
public static FrameworkElement CreateFrameworkElementFromObject(object sourceObject, ResourceDictionary resourceDictionary) 
{ 
    // Find a DataTemplate defined for the DataType 
    DataTemplate dataTemplate = resourceDictionary[new DataTemplateKey(sourceObject.GetType())] as DataTemplate; 
    if (dataTemplate != null) 
    { 
     // Load the content for the DataTemplate 
     FrameworkElement frameworkElement = dataTemplate.LoadContent() as FrameworkElement; 

     // Set the DataContext of the loaded content to the supplied object 
     frameworkElement.DataContext = sourceObject; 

     // Return the content 
     return frameworkElement; 
    } 

    // Return a TextBlock if no DataTemplate is found for the source object data type 
    TextBlock textBlock = new TextBlock(); 
    Binding binding = new Binding(String.Empty); 
    binding.Source = sourceObject; 
    textBlock.SetBinding(TextBlock.TextProperty, binding); 
    return textBlock; 
} 
+0

Voglio qualcosa che faccia esattamente come fa la classe Contenuto. ad esempio segue la stessa logica del controllo del contenuto stesso. Il codice è buono e andrebbe bene per lo scenario DataTemplate. Ma potrebbe non esserci un DataTemplate definito per il mio POCO. –

+0

Se non c'è un DataTemplate corrispondente, ricomincia a creare un TextBlock e usando ToString() sull'oggetto POCO per definire il testo. –

+0

Abbastanza semplice, ho appena aggiornato il metodo per creare un TextBox invece di restituire null se non viene trovato DataTemplate. FYI - ContentControl mostrerà il contenuto di UIElement come UIElement, quindi non utilizzare questo metodo se hai già un UIElement come contenuto. –