如何在 c # 代码中构建 DataTemplate?

我正在尝试建立一个 winform 互操作下拉列表,我正在创建下拉代码。但是,我在根据我指定的 DataTemplate 绑定数据时遇到了问题。

我错过了什么?

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;
95280 次浏览

Assuming that you've already set up the ItemsSource etc for 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;

You can use the same way I have set the ToolTip on the TextBlocks to set other properties such as margins.

Well, indeed we still have another way, you will really like it if you dislike those FrameworkElementFactory things.

And I think it just makes minor changes to the natural code, that is, declare a UserControl and put your control into it, and then, use just one FrameworkElementFactory to call the UserControl.

Simple 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)

The full version

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;