Представление привязки WPF как содержимого
Я экспериментирую с некоторым кодом, где мне нужно смешать программно созданные элементы управления с элементами управления, определенными в 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();
}
}
1 ответ:
Прочитайте это от Microsoft: Проблема привязки изображения-свойство вызывается дважды для каждого элемента
Опубликовано Microsoft 28.04.2010 в 10: 10 утра это не ошибка. WPF (или любой другой код) может вызвать ваш property-getter в любое время для любого причина; нет правила, что он будет вызван только один раз. WPF (и другие абоненты) ожидает, что ваше свойство следует рекомендациям .Net; в частности, что свойство-добытчик быстро, и что он будет возвращает то же значение от звонка до звонка, если только вы не подняли уведомление об изменении свойств.
Поскольку вам любопытно, причина дополнительного вызова заключается в том, что WPF 4.0 выполняет ли некоторую дополнительную работу, когда значение свойства является DependencyObject, проверка, может ли он вызвать изменение" суб-свойства" уведомления (Freezables-главный пример). Эта работа должна быть сделано во время настройки пути привязки, перед выполнением первого перемещение. Мы могли бы скрутить код в узлы, чтобы избежать лишнего фетч, но фетчи стоят дешево.
В принципе, вы не можете полагаться на геттер для объекта DependencyObject, который будет вызван ровно один раз.