C# 绑定到WPF中附加属性中的嵌套元素
我试图将嵌套在附加属性内的元素绑定到我的C# 绑定到WPF中附加属性中的嵌套元素,c#,wpf,xaml,data-binding,attached-properties,C#,Wpf,Xaml,Data Binding,Attached Properties,我试图将嵌套在附加属性内的元素绑定到我的DataContext,但问题是附加属性不是逻辑树的一部分,因此无法正确设置或绑定到父对象的数据上下文。在本例中,值的依赖项属性始终为空 下面是一些XAML示例 <StackPanel> <!-- attached property of static class DataManager --> <local:DataManager.Identifiers> <local:TextI
DataContext
,但问题是附加属性不是逻辑树的一部分,因此无法正确设置或绑定到父对象的数据上下文。在本例中,值
的依赖项属性始终为空
下面是一些XAML示例
<StackPanel>
<!-- attached property of static class DataManager -->
<local:DataManager.Identifiers>
<local:TextIdentifier Value="{Binding Path=MyViewModelString}" />
<local:NumericIdentifier Value="{Binding Path=MyViewModelInt}" />
<local:NumericIdentifier Value="{Binding Path=SomeOtherInt}" />
</local:DataIdentifiers>
<!-- normal StackPanel items -->
<Button />
<Button />
</StackPanel>
我已经尝试过使基类标识符
实现可自由化
,希望它能用于数据继承和绑定上下文,但没有任何效果(可能是因为它嵌套在另一层中-附加属性)
还有几个要点:
- 我希望它能在任何
上工作,而不仅仅是UIElement
sStackPanel
不是可视树的一部分。它们没有也不应该有视觉元素标识符
- 由于这是一个内部库,我希望避免要求绑定使用
或源代码
,因为这样做并不直观相对源代码
DataContext
?我是否需要手动将它们添加到逻辑树中?如果是,怎么做
谢谢 除了让
标识符
继承自Freezable
,您还需要使用FreezableCollection
而不是Collection
作为附加属性类型。这将确保继承链不会断开
public class Identifier : Freezable
{
... // dependency properties
protected override Freezable CreateInstanceCore()
{
return new Identifier();
}
}
创建自定义集合:
public class IdentifierCollection : FreezableCollection<Identifier> { }
示例用法:
除了从
Freezable
继承标识符
之外,还需要使用FreezableCollection
而不是集合
作为附加属性类型。这将确保继承链不会断开
public class Identifier : Freezable
{
... // dependency properties
protected override Freezable CreateInstanceCore()
{
return new Identifier();
}
}
创建自定义集合:
public class IdentifierCollection : FreezableCollection<Identifier> { }
示例用法:
您是否考虑过对DataManager.Identifiers属性使用多重绑定?它将使用一个IMultiValueConverter返回一个
集合
,这也将解决您如何使用集合实例初始化标识符
属性的问题。这可能只需要使用一个附加属性就行了,但它还为混合、转换器甚至更多标记添加了另一个要求。我可以试一试,但希望有一个更干净的解决方案。您是否考虑过对DataManager.Identifiers属性使用多重绑定?它将使用一个IMultiValueConverter返回一个集合
,这也将解决您如何使用集合实例初始化标识符
属性的问题。这可能只需要使用一个附加属性就行了,但它还为混合、转换器甚至更多标记添加了另一个要求。我可以试一试,但希望有一个更干净的解决方案。FreezableCollection
是我缺少的链接。这非常有效-谢谢<代码>FreezableCollection是我丢失的链接。这非常有效-谢谢!
[ContentProperty("IdentifiersProperty")]
public static class DataManager
{
public static readonly DependencyProperty IdentifiersProperty =
DependencyProperty.RegisterAttached(
"Identifiers",
typeof(IdentifierCollection),
typeof(DataManager),
new FrameworkPropertyMetadata(OnIdentifiersChanged));
...
public static void SetIdentifiers(UIElement element, IdentifierCollection value)
{
element.SetValue(IdentifiersProperty, value);
}
public static IdentifierCollection GetIdentifiers(UIElement element)
{
return element.GetValue(IdentifiersProperty) as IdentifierCollection;
}
}
<Window.DataContext>
<local:TestViewModel
MyViewModelInt="123"
MyViewModelString="Test string"
SomeOtherInt="345" />
</Window.DataContext>
<StackPanel x:Name="ParentPanel" ... >
<!-- attached property of static class DataManager -->
<local:DataManager.Identifiers>
<local:IdentifierCollection>
<local:TextIdentifier Value="{Binding Path=MyViewModelString}" />
<local:NumericIdentifier Value="{Binding Path=MyViewModelInt}" />
<local:NumericIdentifier Value="{Binding Path=SomeOtherInt}" />
</local:IdentifierCollection>
</local:DataManager.Identifiers>
<!-- normal StackPanel items -->
<TextBlock Text="{Binding Path=(local:DataManager.Identifiers)[0].Value,
ElementName=ParentPanel, StringFormat=Identifer [0]: {0}}" />
<TextBlock Text="{Binding Path=(local:DataManager.Identifiers)[1].Value,
ElementName=ParentPanel, StringFormat=Identifer [1]: {0}}" />
<TextBlock Text="{Binding Path=(local:DataManager.Identifiers)[2].Value,
ElementName=ParentPanel, StringFormat=Identifer [2]: {0}}" />
</StackPanel>