簡體   English   中英

綁定到 WPF 中附加屬性中的嵌套元素

[英]Binding to Nested Element in Attached Property in WPF

我試圖將嵌套在附加屬性內的元素綁定到我的DataContext ,但問題是附加屬性不是邏輯樹的一部分,因此沒有正確設置或綁定到父對象的數據上下文。 依賴屬性(在本例中為Value )始終為 null。

這是一些示例 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>

由於實現,這不能是單個附加屬性 - 它需要是一個允許n 個實體的集合。 另一個可接受的解決方案是將標識符直接放在節點中,但我認為如果不將這些元素明確包含在邏輯樹中,這種語法是不可能的。 IE..

<Button>
    <local:NumericIdentifier Value="{Binding}" />
    <local:TextIdentifier Value="{Binding}" />
    <TextBlock>Actual button content</TextBlock>
</Button>

這是DataManager實現的開始。

[ContentProperty("IdentifiersProperty")]
public static class DataManager
{
    public static Collection<Identifier> GetIdentifiers(DependencyObject obj)
    {
        return (Collection<Identifier>)obj.GetValue(IdentifiersProperty);
    }

    public static void SetIdentifiers(DependencyObject obj, Collection<Identifier> value)
    {
        obj.SetValue(IdentifiersProperty, value);
    }

    public static readonly DependencyProperty IdentifiersProperty =
        DependencyProperty.RegisterAttached("Identifiers", typeof(Collection<Identifier>), typeof(DataManager), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnIdentifiersChanged)));
}

我已經嘗試讓基類Identifiers實現Freezable ,希望它可以用於數據和綁定上下文的繼承,但這沒有任何效果(可能是因為它嵌套在另一個層中 - 附加屬性)。

還有幾個關鍵點:

  • 我希望這適用於任何UIElement ,而不僅僅是StackPanel s
  • Identifier不是可視化樹的一部分。 他們沒有也不應該有視覺元素
  • 由於這是一個內部庫,我寧願避免將SourceRelativeSource用於綁定,因為需要這樣做並不直觀

是否可以在標記的這一層綁定到繼承的DataContext 我是否需要手動將這些添加到邏輯樹中? 如果是這樣,如何?

謝謝!

除了讓IdentifierFreezable繼承之外,您還需要使用FreezableCollection而不是Collection<Identifier>作為附加屬性類型。 這將確保繼承鏈不被破壞。

public class Identifier : Freezable
{
    ... // dependency properties 

    protected override Freezable CreateInstanceCore()
    {
        return new Identifier();
    }
}

創建自定義集合:

public class IdentifierCollection : FreezableCollection<Identifier> { }

並且,修改附加屬性以使用此集合:

[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>

示例演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM