如何在 XAML 对象上设置附加属性 MyPage.MyParagraph.Text

Posted

技术标签:

【中文标题】如何在 XAML 对象上设置附加属性 MyPage.MyParagraph.Text【英文标题】:How to set Attached property MyPage.MyParagraph.Text on a XAML object 【发布时间】:2019-04-12 15:03:25 【问题描述】:

是否可以在一个对象的多个层中获取/设置附加属性?

虚拟示例:

<ContentControl local:MyPage.Paragraph1.Text="I'm actually a lot of text"/>

还有我的虚拟班级

public static class MyPage

     public static readonly Paragraph1 = new Paragraph();
     public static Paragraph2 get; = new Paragraph();


public class Paragraph

     public readonly DependencyProperty TextProperty;
     public void SetParagraph(DependencyObject obj, string text) => obj.SetValue(TextProperty, text);
     public void GetParagraph(DependencyObject obj) => (string)obj.GetValue(TextProperty);

     public Paragraph()
     
         //note that this is NOT a static Dependency Property. Instead, each instance of this class will be static.
         TextProperty = DependencyProperty.RegisterAttached("Text", typeof(string), typeof(Paragraph), new PropertyMetadata(string.Empty));
     

我尝试了不同的格式,例如 Paragraph2,将 XAML 调用包装在括号中,以及不寻常的 '+' 语法建议 here,但我不断收到如下错误:“属性 'MyPage.Paragraph1.Text' 没有存在于 XML 命名空间“....”中”、“在类型“MyPage”中找不到可附加属性“Paragraph1””和“不得为嵌套类”。

【问题讨论】:

【参考方案1】:

对于附加属性,Get 和 Set 方法应该与属性名称相关联,而不是与定义它的类相关联。

如果一个属性可以附加到可视化树中任意深度的元素,我有一个对我有用的辅助函数。

这是我将如何处理页面/段落:

public class MyPage : Panel

    // implementation of custom panel excluded for clarity


public class Paragraph

    public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(
        "Text",
        typeof(string),
        typeof(CustomContainer),
        new FrameworkPropertyMetadata(null)
    );

    public static void SetText(UIElement element, string value)
    
        element.SetValue(TextProperty, value);
    

    public static string GetText(UIElement element)
    
        return (string)element.GetValue(TextProperty);
    

XAML:

<ctls.MyPage>
    <ctls.Paragraph x:Name="anInstanceOfParagraph">
        <StackPanel>
            <TextBlock ctls:Paragraph.Text="ChapterTitle" Text="Chapter One: My Early Years"/>
        </StackPanel>
    </ctls.Paragraph>
</ctls.MyPage>

在代码中附加属性:

private void AttachText(TextBlock textElement, string text)

    Paragraph.SetText(textElement, text);

然后我们在 Paragraph 中找到任意嵌套的元素,这些元素附加了属性并使用帮助器设置为特定值:

var elements = WPFHelper.GetChildrenWithPropertySet(anInstanceOfParagraph,
                   TextProperty,
                   "IsIntubationCompleted");

这里是辅助函数,WPFHelper 类中的一个静态方法:

/// <summary>
/// Give a property and a control, find all the child controls that
/// have a property (typically an attached property). Optionally,
/// if value !=null, it will search for an item with the property
/// set to a specific value
/// </summary>
/// <param name="parent"></param>
/// <param name="property"></param>
/// <param name="value"></param>
/// <returns></returns>
public static List<DependencyObject> GetChildrenWithPropertySet(DependencyObject parent,
    DependencyProperty property, string value = null)

    var objectsWithPropertySet = new List<DependencyObject>();
    if (value == null)
    
        objectsWithPropertySet.AddRange(parent.GetAllChildren()
            .Where(o => o.ReadLocalValue(property) != DependencyProperty.UnsetValue));
    
    else
    
        objectsWithPropertySet.AddRange(parent.GetAllChildren()
            .Where(o => o.ReadLocalValue(property) != DependencyProperty.UnsetValue &&
                        ((string)o.ReadLocalValue(property)) == value));
    

    return objectsWithPropertySet;


/// <summary>
/// returns all children in the visual true of a dependency object
/// </summary>
/// <param name="parent"></param>
/// <returns></returns>
public static IEnumerable<DependencyObject> GetAllChildren(this DependencyObject parent)

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
    
        // retrieve child at specified index
        var directChild = (Visual)VisualTreeHelper.GetChild(parent, i);

        // return found child
        yield return directChild;

        // return all children of the found child
        foreach (var nestedChild in directChild.GetAllChildren())
            yield return nestedChild;
    

【讨论】:

以上是关于如何在 XAML 对象上设置附加属性 MyPage.MyParagraph.Text的主要内容,如果未能解决你的问题,请参考以下文章

WPF中XAML的触发器的属性,事件 都有那些?以及如何寻找

XAML:DependecyObject 上的属性在它是附加集合中的项目时不会更新

XAML:DependecyObject上的属性在附加集合中的项目时不会更新

绑定到 ResourceDictionary 中的属性

如何使用 DataContext 属性在 XAML 中的窗口上设置 ViewModel?

如何使用DataContext属性在XAML中的窗口上设置ViewModel?