【问题标题】:How to set Attached property MyPage.MyParagraph.Text on a XAML object如何在 XAML 对象上设置附加属性 MyPage.MyParagraph.Text
【发布时间】:2023-03-05 00:45:01
【问题描述】:

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

虚拟示例:

<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””和“不得为嵌套类”。

【问题讨论】:

    标签: xaml attached-properties


    【解决方案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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多