我从一个复杂的实际项目中创建了一个较小的测试项目,但想法是一样的。两者都有同样的问题。
我有两个类,A和B.A是一种ContentControl,B是一种FrameworkElement。 A具有依赖属性Bee(B的类型)。 B具有依赖属性Text(字符串的类型)。 A的默认值为null,B的默认值为" B There!"。
我在测试窗口(Window.Resources)中使用样式将B&#39的Text属性设置为默认值以外的其他属性。
<Window.Resources>
<Style TargetType="local:B">
<Setter Property="Text" Value="YO!!!"/>
</Style>
</Window.Resources>
当我将A.Content设置为B的新实例时,一切都像魅力一样,因为系统处理所有事情。即当我在Visual Studio的设计器中更改样式设置器的值时,它会更改相应的属性值(B.Text)。数据绑定也很好。
<local:A.Content>
<local:B/>
</local:A.Content>
我真正需要的是......
由于我无法控制的原因,我无法使用A.Content,因此我创建了一个新的B实例并将其设置为A.Bee属性。在这种情况下,隐式样式和数据上下文继承不起作用。即当我更改样式设置器的值时,没有任何反应,数据绑定也不起作用。
<local:A.Bee>
<local:B/>
</local:A.Bee>
在A.Bee属性值更改回调中我使用AddLogicalChild,AddVisualChild和数据绑定将B实例放入树中并使数据绑定工作。即当A.Bee设置时,下面发生(简化)......
private static void BeeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
A instanceOfA = d as A;
B newValue = e.NewValue as B;
Binding b = new Binding("DataContext");
b.Source = instanceOfA;
BindingOperations.SetBinding(newValue, B.DataContextProperty, b);
instanceOfA.AddLogicalChild(newValue);
instanceOfA.AddVisualChild(newValue);
}
这解决了数据绑定问题。不确定这是否是正确的方法,但它的工作原理。如果有更好的方法,请告诉我。但是,样式仍然无法在Visual Studio的设计器中使用。
如何在Visual Studio的设计器中更改样式设置器的值时,如何绑定样式值以便更改属性值?
在使用AddLogicalChild之前,newValue的资源没有样式,所以我想我在正确的轨道上但不完全在那里,但是......
如果有人想测试/修改它,我可以在项目中添加链接。
这是测试解决方案的链接(Visual Studio 2013):FEStyleTesting
简而言之,我希望将A.Bee属性设置为B类的实例,就像使用B类实例设置A.Content属性一样。即使用Visual Studio Designer时,数据上下文和样式将继承到B类的实例。
在图像中,我正在调试设计器,正如您所看到的,可以在调用AddLogicalChild之后从资源中找到样式设置器,但由于某种原因,样式未应用于设计器中...在设计师中,还有InstantietedElementViewNode属性的第三个设置器。即在运行时它没有。也许它是设计师为每个控件添加的东西......前两个setter是在XAML中定义的(忘了为图片展开它们)。
只是为了澄清,在测试应用程序中,想法是使用消息框进行测试。即我不需要改变视觉外观(使用Content属性时会这样做)。只需在XAML中更改样式设置器值时调用回调。
以下是测试此问题的步骤:
B是故意从ContentControl(而不是FrameworkElement)派生的,因此我可以在使用A.Content属性时验证数据绑定和样式继承。 ContentControl派生自FrameworkElement,因此结果应该相同。 FrameworkElement用于我的大型项目。
在调试设计师时,我改变了#34; YO !!!&#34;到&#34; YO2 !!!&#34;然后在XAML中显式更改了B.Color。然后在ColorChanged回调中,我查看了B实例的资源,发现该值已相应更改。因此,当我在XAML中更改样式值时,样式值会更新,但由于某些原因它们不会更改属性值(文本仍然是#34; YO !!!&#34;)...因此,没有调用回调
我想知道是什么原因造成的......
我可能找到了可能的解决方案。我注意到即使我调用AddLogicalChild,A.LogicalChildren也没有包含B对象。然后我经历了可覆盖的方法并遇到了可覆盖的LogicalChildren属性。
这是我的版本:
protected override IEnumerator LogicalChildren
{
get
{
List<object> list = new List<object>();
while (base.LogicalChildren.MoveNext() == true)
{
try
{
list.Add(base.LogicalChildren.Current);
}
catch
{
// If Current fails, break.
break;
}
}
list.Add(Bee);
return list.GetEnumerator();
}
}
不确定这是否是&#34;终极&#34;解决方案,但现在每次更改样式设置器值时,都会调用我的属性更改回调。好吧,生活和学习......更好地测试一下。
答案 0 :(得分:0)
因此问题的答案是覆盖LogicalChildren属性以包含嵌套对象。这也将消除BindingOperations绑定到DataContext的需要。仍然需要AddLogicalChild。不确定AddVisualChild但是比抱歉更安全......