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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/248362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:49:10  来源:igfitidea点击:

How do I build a DataTemplate in c# code?

c#wpfdatatemplate

提问by

I am trying to build a dropdown list for a winform interop, and I am creating the dropdown in code. However, I have a problem getting the data to bind based on the DataTemplate I specify.

我正在尝试为 winform 互操作构建下拉列表,并且我正在代码中创建下拉列表。但是,我在根据我指定的 DataTemplate 获取要绑定的数据时遇到问题。

What am I missing?

我错过了什么?

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;

采纳答案by Donnelle

Assuming that you've already set up the ItemsSourceetc for drpCreditCardNumberWpf...

假设您已经ItemsSourcedrpCreditCardNumberWpf...

//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 ToolTipon the TextBlocks to set other properties such as margins.

您可以使用我ToolTipTextBlocks 上设置的相同方式来设置其他属性,例如边距。

回答by a_a

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

嗯,确实我们还有另外一种方式,如果你不喜欢那些FrameworkElementFactory东西,你会真的喜欢它。

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

而且我认为它只是对自然代码进行了微小的更改,即声明 aUserControl并将您的控制权放入其中,然后仅使用一个FrameworkElementFactory来调用UserControl.

Simple demo code (in F#):

简单的演示代码(在 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)

回答by Pavlo Datsiuk

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;