WPF绑定查看内容 [英] WPF Binding View as Content

查看:194
本文介绍了WPF绑定查看内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我与一些code,我需要在XAML定义控制模式,混合编程方式创建的控件进行实验。

有人可以解释为什么当我绑定到元素视图属性,属性的'得到'被调用了两次,但绑定到Template属性,当它被调用一次(如预期)。

示例输出时,结合景观:

  StringElement
StringElement
BoolElement
BoolElement
StringElement
StringElement

示例输出时绑定到模板:

  StringElement
BoolElement
StringElement

-

 <窗​​口x:类=BindView.MainWindow
    的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
    的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
    标题=主窗口WindowStartupLocation =中心屏幕>
<的ItemsControl的ItemsSource ={绑定元素}>
    < ItemsControl.ItemTemplate>
        <&DataTemplate的GT;
            <内容presenter CONTENT ={绑定视图}/>
        < / DataTemplate中>
        <! - <&DataTemplate的GT;
            <内容presenter的ContentTemplate ={绑定模板}/>
        &所述; /的DataTemplate&GT - →;
    < /ItemsControl.ItemTemplate>
< / ItemsControl的>

 公共抽象类元素
{
    公众的DataTemplate模板
    {
        得到
        {
            Console.WriteLine(的GetType()名称。);
            返回OnGetTemplate();
        }
    }    公共抽象的DataTemplate OnGetTemplate();    公众的UIElement查看
    {
        得到
        {
            Console.WriteLine(的GetType()名称。);
            返回OnGetView();
        }
    }    公共抽象的UIElement OnGetView();    受保护的DataTemplate CreateTemplate(类型viewType)
    {
        VAR XAML =的String.Format(<&DataTemplate的GT;< {0} />< / DataTemplate中>中,viewType.Name);
        VAR语境=新ParserContext();        context.XamlTypeMapper =新XamlTypeMapper(新的字符串[0]);
        context.XmlnsDictionary.Add(,http://schemas.microsoft.com/winfx/2006/xaml/$p$psentation);
        context.XmlnsDictionary.Add(×,http://schemas.microsoft.com/winfx/2006/xaml);        返回(DataTemplate中)XamlReader.Parse(XAML,背景);
    }
}公共类StringElement:元
{
    公众覆盖的DataTemplate OnGetTemplate(){返回CreateTemplate(typeof运算(文本框)); }
    公众覆盖的UIElement OnGetView(){返回新的TextBox(); }
}公共类BoolElement:元
{
    公众覆盖的DataTemplate OnGetTemplate(){返回CreateTemplate(typeof运算(复选框)); }
    公众覆盖的UIElement OnGetView(){返回新的复选框(); }
}公共部分类主窗口:窗口
{
    公开名单<组件>元素{搞定;私人集; }    公共主窗口()
    {
        元素=新的List<组件>(){新StringElement(),新BoolElement(),新StringElement()};
        的DataContext =这一点;
        的InitializeComponent();
    }
}


解决方案

从微软阅读:<一href=\"http://connect.microsoft.com/VisualStudio/feedback/details/554237/problem-binding-image-property-called-twice-for-each-item\"相对=nofollow>问题结合图像 - 属性为每个项目叫了两声


  

发布Microsoft在2010/4/28在10:10 AM这是不是一个错误。 WPF
  (或任何其他code)可以在任何时间以任何打电话给你的财产的getter
  原因;没有规则,这将是一次调用。 WPF(和
  其他用户)预计,你的财产遵循的.Net准则;
  特别是与属性吸气剂是快,而且它会
  从调用返回相同的值来调用,除非你提出了一个
  属性更改通知。


  
  

既然你很好奇,对于额外调用的原因是WPF 4.0
  做一些额外的工作,当属性值是一个DependencyObject的,
  检查,看它是否能够提高分财产的变化
  通知(Freezables是主要的例子)。这项工作必须
  完成在设置绑定路径,做之前先
  转让。我们可以扭曲code在海里,以避免额外
  取,但取很便宜。


基本上你可以不依赖于getter方法​​为DependencyObject被调用一次。

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

解决方案

Read this from Microsoft: Problem binding image - property called twice for each item

Posted by Microsoft on 4/28/2010 at 10:10 AM This is not a bug. WPF (or any other code) can call your property-getter at any time for any reason; there's no rule that it will be called only once. WPF (and other callers) expects that your property follows the .Net guidelines; in particular that the property-getter is fast, and that it will return the same value from call to call unless you've raised a property-changed notification.

Since you're curious, the reason for the extra call is that WPF 4.0 does some extra work when the property value is a DependencyObject, checking to see whether it can raise "sub-property" change notifications (Freezables are the chief example). This work must be done while setting up the binding path, before doing the first transfer. We could have twisted the code in knots to avoid an extra fetch, but fetches are cheap.

Basically you can't rely the getter for a DependencyObject to be called exactly once.

这篇关于WPF绑定查看内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆