Joan Venge
Joan Venge

Reputation: 331042

How to setup a WPF datatemplate in code for a treeview?

struct Drink
{
    public string Name { get; private set; }
    public int Popularity { get; private set; }

    public Drink ( string name, int popularity )
        : this ( )
    {
        this.Name = name;
        this.Popularity = popularity;
    }
}

List<Drink> coldDrinks = new List<Drink> ( ){
    new Drink ( "Water", 1 ),
    new Drink ( "Fanta", 2 ),
    new Drink ( "Sprite", 3 ),
    new Drink ( "Coke", 4 ),
    new Drink ( "Milk", 5 ) };
        }
    }

So that I can see the Name property for treeview item names.

Upvotes: 3

Views: 11052

Answers (3)

Guish
Guish

Reputation: 5160

Instead of creating your own XAML like Reed said you can get a control XAML by using

String myXAML = System.Windows.Markup.XamlWriter.Save(yourControl.Template)

You can then edit the XAML and create back your controltemplate/datatemplate

var xamlStream = new MemoryStream(System.Text.Encoding.Default.GetBytes(myXAML));
_buttonControlTemplate = (ControlTemplate)System.Windows.Markup.XamlReader.Load(xamlStream);

Upvotes: 4

itowlson
itowlson

Reputation: 74802

Reed has already covered the "build your own XAML" approach, but just to provide an illustration of the FrameworkElementFactory approach, it would look something like this.

First, create the FEF:

var fef = new FrameworkElementFactory(typeof(TextBlock));
fef.SetBinding(TextBlock.TextProperty, new Binding("Name"));

Then create a DataTemplate with its VisualTree set to that factory:

DataTemplate dt = new DataTemplate { VisualTree = fef };

Although as Reed notes the FrameworkElementFactory approach is officially deprecated, it is still reasonably widely used, I guess because building XAML strings feels so kludgy. (Though the FEF approach rapidly becomes insanely complicated if you have a non-trivial template...!)

Upvotes: 3

Reed Copsey
Reed Copsey

Reputation: 564413

There are two approaches. The easiest is to just generate the xaml, and parse it at runtime:

string xaml = "<DataTemplate><TextBlock Text=\"{Binding Name}\"/></DataTemplate>";
MemoryStream sr = new MemoryStream(Encoding.ASCII.GetBytes(xaml));
ParserContext pc = new ParserContext();
pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
DataTemplate datatemplate = (DataTemplate)XamlReader.Load(sr, pc);
treeView1.Resources.Add("dt", datatemplate);

The second option is to use the FrameworkElementFactory class. However, this is quite involved, and difficult to get "right". As MSDN now refers to this as deprecated, I won't include code to demonstrate...

Upvotes: 7

Related Questions