WPF: How to accept both string and FrameworkElement in a dependency property (e.g. wpf Label)?

I am creating a WPF user control that needs to have multiple content slots. I would like the user to be able to use any string or FrameworkElement as a property value, for example:

<!-- MyHeading is a string -->
<MyControl MyHeading="Hello World" />

<MyControl>
    <!-- MyHeading is a FrameworkElement -->
    <MyControl.MyHeading>
        <Expander Header="Hello">
            World
        </Expander>
    </MyControl.MyHeading>
</MyControl>

I know that WPF ContentControl does this (accepts both strings and other elements), and I know that it has something to do with the attribute TypeConverter( partially explained here ), but I tried to look at ContentControl, Label, TextBlock and other elements control in Reflector, and did not find any TypeConverter there, and googling did not help.

, , , , FrameworkElement :

public FrameworkElement Heading
{
    get { return (FrameworkElement)GetValue(HeadingProperty); }
    set { SetValue(HeadingProperty, value); }
}

// Using a DependencyProperty as the backing store for Heading.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeadingProperty =
    DependencyProperty.Register("Heading", typeof(object), typeof(DialogControl), new UIPropertyMetadata(new FrameworkElement()));

:

public object Heading
{
    get { return (object)GetValue(HeadingProperty); }
    set
    {
        if (value is string)
        {
            var tb = new TextBlock();
            tb.Text = (string) value;
            tb.FontSize = 20;
            SetValue(HeadingProperty, tb);
        }
        else if (value is FrameworkElement)
        {
            SetValue(HeadingProperty, value);
        } else 
            throw new ArgumentOutOfRangeException("Heading can take only string or FrameworkElement.");
    }
}

// Using a DependencyProperty as the backing store for Heading.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeadingProperty =
    DependencyProperty.Register("Heading", typeof(object), typeof(DialogControl), new UIPropertyMetadata(null));

: (.

- , ? !

+3
3

DependencyProperty Object. , Content ContentPresenter. ContentSource, .

+3

, . WPF , ( DataTemplate), Object ToString() . , , DateTime, Enum, .

, HeaderedContentControl, , . , , .

+1

, . , . .

public object Header
    {
        get { return (object)GetValue(HeadingProperty); }
        set { SetValue(HeadingProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty HeadingProperty = DependencyProperty.Register(
        "Heading",
        typeof(object),
        typeof(DialogControl),
        new UIPropertyMetadata(null),
        new ValidateValueCallback(Heading_Validation)
        );

    private static bool Heading_Validation(object source)
    {
        return source is string||
            source is FrameworkElement ||
            source == null;
    }

, , String, FrameworkElement null.

!

0
source

Source: https://habr.com/ru/post/1723571/


All Articles