I'm experimenting with some code where I need to mix programmatically created controls with controls defined in XAML.
Can someone explain why when I bind to the Elements View property, the property's 'get' is called twice, yet when binding to the Template property it gets called only once (as expected).
Example output when binding to View :
StringElement
StringElement
BoolElement
BoolElement
StringElement
StringElement
Example output when binding to Template :
StringElement
BoolElement
StringElement
--
<Window x:Class="BindView.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" WindowStartupLocation="CenterScreen">
<ItemsControl ItemsSource="{Binding Elements}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding View}" />
</DataTemplate>
<!--<DataTemplate>
<ContentPresenter ContentTemplate="{Binding Template}" />
</DataTemplate>-->
</ItemsControl.ItemTemplate>
</ItemsControl>
public abstract class Element
{
public DataTemplate Template
{
get
{
Console.WriteLine(GetType().Name);
return OnGetTemplate();
}
}
public abstract DataTemplate OnGetTemplate();
public UIElement View
{
get
{
Console.WriteLine(GetType().Name);
return OnGetView();
}
}
public abstract UIElement OnGetView();
protected DataTemplate CreateTemplate(Type viewType)
{
var xaml = string.Format("<DataTemplate><{0} /></DataTemplate>", viewType.Name);
var context = new ParserContext();
context.XamlTypeMapper = new XamlTypeMapper(new string[0]);
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
return (DataTemplate)XamlReader.Parse(xaml, context);
}
}
public class StringElement : Element
{
public override DataTemplate OnGetTemplate() { return CreateTemplate(typeof(TextBox)); }
public override UIElement OnGetView() { return new TextBox(); }
}
public class BoolElement : Element
{
public override DataTemplate OnGetTemplate() { return CreateTemplate(typeof(CheckBox)); }
public override UIElement OnGetView() { return new CheckBox(); }
}
public partial class MainWindow : Window
{
public List<Element> Elements { get; private set; }
public MainWindow()
{
Elements = new List<Element>() { new StringElement(), new BoolElement(), new StringElement() };
DataContext = this;
InitializeComponent();
}
}