惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Simon Willison's Weblog
Simon Willison's Weblog
P
Privacy International News Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
Troy Hunt's Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Attack and Defense Labs
Attack and Defense Labs
S
Secure Thoughts
V2EX - 技术
V2EX - 技术
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
O
OpenAI News
Cloudbric
Cloudbric
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Help Net Security
Help Net Security
Cyberwarzone
Cyberwarzone
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Spread Privacy
Spread Privacy
NISL@THU
NISL@THU
N
News and Events Feed by Topic
T
Tenable Blog
S
Security @ Cisco Blogs
N
News and Events Feed by Topic
The Hacker News
The Hacker News
C
CXSECURITY Database RSS Feed - CXSecurity.com
宝玉的分享
宝玉的分享
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google DeepMind News
Google DeepMind News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
V
Visual Studio Blog
P
Proofpoint News Feed
Webroot Blog
Webroot Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 三生石上(FineUI控件)
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Jina AI
Jina AI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
L
LangChain Blog
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东

博客园 - idior

每日代码 - 7/1 减小方法参数的依赖 每日代码 - 6/29 读写分离 每日代码 - 6/28 代码逻辑分组 每日代码 - 6/26 lambda表达式 每日代码 - 6/27 避免创建非法对象 Resume Covariance and Contravariance How does ElementName Binding work? Weird behavior of DataContext Inheritance How does ElementName Binding work – Part 3 InheritanceContext Logical Tree & Visual Tree Memory leak caused by EventHandle - weak event Resources on Debugging/Tracing WPF How does ElementName Binding work? - Part 1 Logical Tree & NameScope Inside WCF Runtime 有谁准备参加10月份的MVP聚会? MVP聚会 Practical .NET2 and C#2 翻译样章 Be evil or not?
How does ElementName Binding work – Part 2 BindingExpression
idior · 2010-06-07 · via 博客园 - idior

In part 1, I gave a general finding rule for ElementName binding, it works in most cases, however there are some cases you cannot explain them with the general rule. I will cover some of them in the following articles which involve some advanced concept in WPF, like BindingExpression and InheritanceContext.

What happens when ElementName binding is used in DataTrigger?

Take a look at following codes:

    <Window x:Class="TestElementBindingInUserControl.MainWindow">
        <local:CustomControl1/>
    </Window>

    <Style TargetType="{x:Type local:CustomControl1}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                    <StackPanel>
                        <Button Name="btn" Content="PFS Button"/>
                        <TextBlock Name="tbk" />
                    </StackPanel>
                    <ControlTemplate.Triggers>
                        <DataTrigger Binding="{Binding ElementName=btn, 
                                                       Path=Content}"                 
                                     Value="PFS Button">
                            <Setter TargetName="tbk" 
                                    Property="Text" 
                                    Value="PFS TextBlock"/>
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Let’s go back to our rules first:

  1. Start from the element which applied the ElementName Binding, keep searching on the logic tree via its logic parent, until an element which has NameScope is found, let’s call it NameScopeElement. If no element owns a NameScope, search will stop.
  2. Call the NameScope.FindName method on the found NameScope.
  3. If the element is found, return it, otherwise try to get the template parent of NameScopeElement; if the template parent is null, it will stop search. or it goes back to step 1, search on the logic tree for element owns a NameScope.

If we start from DataTrigger, you will find its logic parent would be null, the search will not continue.  Ok, I have to acknowledge the original statement is oversimplified.

It actually starts form the TargetElement of the BindingExpression which is created by the ElementName Binding. Here it is the CustomControl1.  A little confused here? Let’s see what’s the BindingExpression and what’s the relationship between a BindingExpression and Binding.

Binding class is the high-level class for the declaration of a binding; the Binding class provides many properties that allow you to specify the characteristics of a binding. A related class,BindingExpression, is the underlying object that maintains the connection between the source and the target. Normally BindingExpression is created by WPF framework, WPF programmer rarely use it in functional codes. A key difference between BindingExpression and Binding is that Binding only contains the Source info while BindingExpression also contains the Target info. That is being said, Binding only tells you where the data comes from, while BindingExpression also defines where the data will transfer to. 

In most cases, the TargetElement of the BindingExpression will be the DependencyObject whose DependencyProperty is set to a Binding MarkupExtension. For example, the TargetElement of the BindingExpression will be set to the Button object in following codes:

<Button Content="{Binding ElementName=root,Path=Title}"/>

However our style of CustomControl1, DataTrigger is not a DependencyObject and Binding property is not a DependencyProperty either.

<DataTrigger Binding="{Binding ElementName=btn, Path=Content}"                 
             Value="PFS Button">

The BindingExpression will be created in a different way than others, it’s created in StyleHelper.GetDataTriggerValue methods which are internal to the WPF framework. In that method, the BindingExpression’s TargetElement will be set to the object which applies the style that defines the DataTrigger.

Ok. We are clear of where should we start the search, let’s continue our search. CustomControl1 doesn’t own a NameScope, so we will get his parent which is Window, since Window has a NameScope, we will call the FindName method on Window’s NameScope, but we still cannot find btn. As I said both Window and ControlTemplate have their own NameScope, btn is registered in ControlTemplate’s NameScope rather than Window, so you cannot find btn in Window’s NameScope.

But if you run the above code, you will see it works. Ok, there is another point i missed in part 1.

When we start the search from the TargetElement of the BindingExpression, it will check  ResolveNamesInTemplate property of the BindingExpression, if it’s true, it will try to find the element defined in its template first. In our case, the BindingExpression is created from a DataTrigger, the ResolveNamesInTemplate is set to true in StyleHelper.GetDataTriggerValue method, now btn can be found.

Let’s revised the finding rule:

  1. Get the BindingExpression which is created by the ElementName Binding.
  2. Start from the TargetElement of the BindingExpression. If the value of BindingExpression’s ResolveNamesInTemplate property is true, it will search in the TargetElement’s template, if an element with the same name can be found in its template then return it, else go to next step.
  3. Keep searching on the logic tree via its logic parent, until an element which has NameScope is found, let’s call it NameScopeElement. If no element owns a NameScope, search will stop.
  4. Call the NameScope.FindName method on the found NameScope.
  5. If the element is found, return it, otherwise try to get the template parent of NameScopeElement; if the template parent is null, it will stop search. or it goes back to step 3, search on the logic tree for an element owns a NameScope.

In part 3, I will give some introduction to InheritanceContext which is also called LogicalParent 2.0. :)