Wie erstelle ich eine DataTemplate in C # -Code?


81

Ich versuche, eine Dropdown-Liste für eine Winform-Interop zu erstellen, und ich erstelle die Dropdown-Liste im Code. Ich habe jedoch ein Problem damit, dass die Daten basierend auf der von mir angegebenen DataTemplate gebunden werden.

Was vermisse ich?

drpCreditCardNumberWpf = new ComboBox();  
DataTemplate cardLayout = new DataTemplate {DataType = typeof (CreditCardPayment)};   
StackPanel sp = new StackPanel
{
    Orientation = System.Windows.Controls.Orientation.Vertical
};   

TextBlock cardHolder = new TextBlock {ToolTip = "Card Holder Name"};
cardHolder.SetBinding(TextBlock.TextProperty, "BillToName");
sp.Children.Add(cardHolder);

TextBlock cardNumber = new TextBlock {ToolTip = "Credit Card Number"};
cardNumber.SetBinding(TextBlock.TextProperty, "SafeNumber");
sp.Children.Add(cardNumber);

TextBlock notes = new TextBlock {ToolTip = "Notes"};
notes.SetBinding(TextBlock.TextProperty, "Notes");
sp.Children.Add(notes);

cardLayout.Resources.Add(sp, null);

drpCreditCardNumberWpf.ItemTemplate = cardLayout;

4
Beachten Sie, dass diese Antworten zu diesem Zeitpunkt zwar korrekt waren, die derzeit empfohlene Methode zum programmgesteuerten Erstellen einer Vorlage jedoch darin besteht, XAML mithilfe der LoadMethode der XamlReaderKlasse aus einer Zeichenfolge oder einem Speicherstrom zu laden .
Sheridan

Antworten:


149

Angenommen, Sie haben das ItemsSourceetc bereits eingerichtet für drpCreditCardNumberWpf...

//create the data template
DataTemplate cardLayout = new DataTemplate();
cardLayout.DataType = typeof(CreditCardPayment);

//set up the stack panel
FrameworkElementFactory spFactory = new FrameworkElementFactory(typeof(StackPanel));
spFactory.Name = "myComboFactory";
spFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);

//set up the card holder textblock
FrameworkElementFactory cardHolder = new FrameworkElementFactory(typeof(TextBlock));
cardHolder.SetBinding(TextBlock.TextProperty, new Binding("BillToName"));
cardHolder.SetValue(TextBlock.ToolTipProperty, "Card Holder Name");
spFactory.AppendChild(cardHolder);

//set up the card number textblock
FrameworkElementFactory cardNumber = new FrameworkElementFactory(typeof(TextBlock));
cardNumber.SetBinding(TextBlock.TextProperty, new Binding("SafeNumber"));
cardNumber.SetValue(TextBlock.ToolTipProperty, "Credit Card Number");
spFactory.AppendChild(cardNumber);

//set up the notes textblock
FrameworkElementFactory notes = new FrameworkElementFactory(typeof(TextBlock));
notes.SetBinding(TextBlock.TextProperty, new Binding("Notes"));
notes.SetValue(TextBlock.ToolTipProperty, "Notes");
spFactory.AppendChild(notes);

//set the visual tree of the data template
cardLayout.VisualTree = spFactory;

//set the item template to be our shiny new data template
drpCreditCardNumberWpf.ItemTemplate = cardLayout;

Sie können auf die gleiche Weise, wie ich das ToolTipon TextBlocks festgelegt habe, andere Eigenschaften wie z. B. Ränder festlegen.


1
In Silverlight 4 ist die Frameworkelementfactory-Klasse nicht vorhanden. Ich möchte xaml.load auch nicht verwenden. Gibt es eine andere Möglichkeit, wie wir es lösen können?
Neugier

1
Für Silverlight 4/5 ... Ref.: Blogs.msdn.com/b/scmorris/archive/2008/04/14/…
Nordes


1

Die Vollversion

var ms = new MemoryStream(Encoding.UTF8.GetBytes(@"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
                                                                 xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""                                                                             
                                                                 xmlns:c=""clr-namespace:MyApp.Converters;assembly=MyApp"">
        <DataTemplate.Resources>
            <c:MyConverter x:Key=""MyConverter""/>
        </DataTemplate.Resources>
        <TextBlock Text=""{Binding ., Converter={StaticResource MyConverter}}""/>
      </DataTemplate>"));
var template = (DataTemplate)XamlReader.Load(ms);

var cb = new ComboBox { };
//Set the data template
cb.ItemTemplate = template;

Hinweis - XamlReader.LoadAkzeptiert keine Ereignishandler.
Mikhail Orlov

-1

Nun, in der Tat haben wir noch einen anderen Weg, Sie werden es wirklich mögen, wenn Sie diese FrameworkElementFactoryDinge nicht mögen .

Und ich denke, es nimmt nur geringfügige Änderungen am natürlichen Code vor, dh deklarieren Sie a UserControlund setzen Sie Ihre Kontrolle darin ein, und verwenden Sie dann nur eine FrameworkElementFactory, um den aufzurufen UserControl.

Einfacher Demo-Code (in F #):

let buildView()=StackPanel()
//Build it with natural code
type MyView()=inherit UserControl(Content=buildView())
let factory=FrameworkElementFactory(typeof<MyView>)
let template=DataTemplate(VisualTree=factory)
let list=ItemsControl(ItemsSource=makeData(),ItemTemplate=template)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.