Tono Nam
Tono Nam

Reputation: 36048

WPF replace UIElement with another

If I have

<StackPanel>
    <Button name="btn"/>
</StackPanel>

how could I replace Button btn for a different control when I press that button? In this case I know the parent is a StackPanel so I could cast the parent to a stackPanel and then replace that child. but what if I have a Border?

<Border>
    <Button name="btn"/>
</Border>

Thanks to McGarnagle I created this extension method

how can I replace a Button with my custom control without knowing in advance the parent of the button?

Edit

    public static void ReplaceWith(this FrameworkElement elementToReplace, FrameworkElement newControl)
    {
        newControl.Width = elementToReplace.Width;
        newControl.Height = elementToReplace.Height;
        newControl.Margin = elementToReplace.Margin;

        // get parent of control
        var parent = elementToReplace.Parent;

        if (parent is Panel)
        {
            var panel = (Panel)parent;

            for (var i = 0; i < panel.Children.Count; i++)
            {
                if (panel.Children[i] == elementToReplace)
                {
                    panel.Children.RemoveAt(i);
                    panel.Children.Insert(i, newControl);
                    break;
                }
            }
        }
        else if (parent is Decorator)
        {
            ((Decorator)parent).Child = newControl;
        }
        else if (parent is ContentControl)
        {
            ((ContentControl)parent).Content = newControl;
        }
        else
        {
            if(Debugger.IsAttached)
                Debugger.Break();

            throw new NotImplementedException("Missing other possibilities to implement");
        }
    }

Upvotes: 1

Views: 1861

Answers (3)

Anatoliy Nikolaev
Anatoliy Nikolaev

Reputation: 22702

Yo can get the logical parent of Control and check it's type using the operator is like this:

var parent = MyButton.Parent;

if (parent is StackPanel)
{ 
    // do something with StackPanel
}

if (parent is Border) 
{
    // do something with Border
}

Upvotes: 1

ad1Dima
ad1Dima

Reputation: 3195

All containers are Panel or ContentControl or UserControl. So you can check if parent is inherited from one of these controls.

Upvotes: 1

McGarnagle
McGarnagle

Reputation: 102743

I suppose you could cycle through the possible base classes. There aren't that many: StackPanel is a Panel, Border is a Decorator, …

var parent = btn.Parent;
var replacement = new TextBlock { Text = "replacement" };
if (parent is Panel)
{ 
    var panel = (Panel)parent;
    panel.Children.Remove(btn);
    panel.Children.Add(replacement);
}
else if (parent is Decorator)
{ 
    ((Decorator)parent).Child = replacement;
}
else if (parent is ContentControl)
{
    ((ContentControl)parent).Content = replacement;
}

Upvotes: 5

Related Questions