Style里创建的UI元素都是共享的

前提是当Style在一个界面上被多次使用(比如MenuItem的Style,如果ItemContainerStyle来设置,使用的是同一个Style,被用到多个menuItem的情况)

就会出现:Specified element is already the logical child of another element. Disconnect it first.

如果错误被吃掉了,界面上就会出现没有被用上Style的元素。

比如

<Style x:Key="m1" TargetType="{x:Type MenuItem}"? BasedOn="{StaticResource {x:Type MenuItem}}" >
?????????? <Setter? Property="Header">
???????????????? <Setter.Value>

??????????????????????? <TextBlock………>

?????????????????? </Setter.Value>
?????????? </Setter>

?????? </Style>

类似这篇文章里提到的现象。解决方案是用x困惑hared = false. 见msdn的解释。

?

<Label x:Shared="false" x:Key="l" Content="{Binding}">
????? </Label>
????? <Style x:Key="m1" TargetType="{x:Type MenuItem}"? BasedOn="{StaticResource {x:Type MenuItem}}" >
????????? <Setter? Property="Header" Value="{StaticResource l}">??????????????
????????? </Setter>
????? </Style>

转载:How does ElementName Binding work

How does ElementName Binding work? – Part 1 Logical Tree & NameScope

How does ElementName Binding work – Part 2 BindingExpression

How does ElementName Binding work – Part 3 InheritanceContext

Weird behavior of DataContext Inheritance

当NameScope不工作的时候,往往是因为不在同一个Scope内,比如

http://stackoverflow.com/questions/6355217/xname-not-working-if-element-wrapped-in-usercontrols-content-silverlight

这时x:Name="tbxNothing"定义发生在主页内(使用MyWrapperPanel的地方),这是一个外部的NameScope,但是却不会把这个TextBox直接加到自己的逻辑树里,Xaml的定义只是设置了一个UserControl的一个属性。而在MyWrapperPanel控件内部,是使用者自己(一个UserControl)的NameScope,它接受外面设置的一个Dependency Property的时候,并不会自动加到自己的NameScope里,也不会更新父亲的NameScope。但是我觉得,这个过程其实由于修改了ContentPresenter的内容,其实可以推导出逻辑树的变化,应该要更改双方的NameScope里的集合才对。

下面这篇这篇也是同样的问题。结果只能靠手动设置NameScope和Register,尤其是如果在外面的animation用了里面的对象,还必须把外面的NameScope传进去,这样才是同一个NameScope。不够这三篇文章的情况是可以理解的,因为涉及了Template,顾名思义,一个模版可以有多个实体共同使用,而且有可能这些实体共享一个父亲对象(在逻辑树中),所以为了保证命名不重复,不会自动传递NameScope是可以理解的。

Dependency Property的ValueSource

用VS自带的WPF visualizor或者Mole插件可以看到某个DP属性的Source列,实际上是ValueSource(http://msdn.microsoft.com/en-us/library/system.windows.valuesource.aspx)这个结构的一部分,BaseValueSource枚举类型。

通过反射看DependencyPropertyHelper.GetValueSource方法可以看到某个DP的Source实际上是放在这个DO对象的

private EffectiveValueEntry[] _effectiveValues;

里面的Entry的BaseValueSourceInternal里,是固定的。

而这个Source的枚举值(而不是DP的实际值)是在第一次给这个DP赋值的时候就定下来了(除非没有赋值过,那么就没有effectiveValue,而是去找metadata)。也就是xaml里如果有P1=XXX,同时又有Style里对P1进行绑定,绑定虽然会触发,试图去生效,但是实际值却传不过去。