我尝试了一些代码,我需要将编程创建的控件与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();
}
}
答案 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。