【问题标题】:WPF Binding View as ContentWPF 绑定视图作为内容
【发布时间】:2014-07-02 23:39:43
【问题描述】:

我正在试验一些代码,我需要将编程创建的控件与 XAML 中定义的控件混合在一起。

有人可以解释为什么当我绑定到 Elements View 属性时,该属性的“get”被调用了两次,而当绑定到 Template 属性时它只被调用一次(如预期的那样)。

绑定到视图时的示例输出:

StringElement
StringElement
BoolElement
BoolElement
StringElement
StringElement

绑定到模板时的示例输出:

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

【问题讨论】:

    标签: c# wpf templates binding contentpresenter


    【解决方案1】:

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

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

    既然你很好奇,额外调用的原因是 WPF 4.0 当属性值为 DependencyObject 时,会做一些额外的工作, 检查它是否可以引发“子属性”更改 通知(Freezables 是主要的例子)。这项工作必须 在设置绑定路径时完成,在做第一个之前 转移。我们本可以将代码扭曲成节,以避免额外的 抓取,但抓取很便宜。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      相关资源
      最近更新 更多