WPF绑定视图作为内容

时间:2014-07-02 23:39:44

标签: c# wpf templates binding contentpresenter

我尝试了一些代码,我需要将编程创建的控件与XAML中定义的控件混合使用。

有人可以解释为什么当我绑定到“元素视图”属性时,属性“获取”'被调用两次,但是当绑定到Template属性时,它只被调用一次(如预期的那样)。

绑定到View时的示例输出:

StringElement
StringElement
BoolElement
BoolElement
StringElement
StringElement

绑定到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();
    }
}

1 个答案:

答案 0 :(得分:2)

从Microsoft阅读:Problem binding image - property called twice for each item

  

Microsoft于2010年4月28日上午10:10发布这不是错误。 WPF   (或任何其他代码)可随时致电您的物业获取者   原因;没有规则它只会被调用一次。 WPF(和   其他来电者)希望您的财产遵循.Net指南;   特别是属性获取器很快,而且它会   除非你提出了一个,否则从call到call返回相同的值   财产变更通知。

     

由于你很好奇,额外通话的原因是WPF 4.0   当属性值是DependencyObject时,做一些额外的工作,   检查是否可以提高“子属性”的变化   通知(Freezables是主要的例子)。这项工作必须是   在完成第一个之前,在设置绑定路径时完成   传递。我们可以将代码扭曲成结以避免额外的   提取,但提取很便宜。

基本上你不能依赖getter来完全调用一次DependencyObject。