Как установить прикрепленное свойство MyPage.MyParagraph.Text для объекта XAML

Можно ли получить/установить прикрепленные свойства на несколько слоев вглубь объекта?

Пример фиктивного:

<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 в круглые скобки, и необычный синтаксис "+", предложенный здесь, но я продолжаю получать такие ошибки, как: «Свойство« MyPage.Paragraph1.Text »не существует в пространстве имен XML« .... »»,« Присоединяемое свойство« Абзац1 »не найдено в типе« Моя страница »» и "не должен быть вложенным классом".


person bwall    schedule 12.04.2019    source источник


Ответы (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;
    }
}
person Kevin Walsh    schedule 12.04.2019