Controls inside a custom control cannot move

I have a custom control (say MyContainer) that is just a ScrollViewer with an inner canvas.

I can add controls to MyContainer as they would to Canvas, but in XAML design, those controls do not move like they would in a regular Canvas; they cannot be moved with the mouse.

Here's the MyContainer code:

[ContentProperty("Children")]
public class MyContainer : ScrollViewer, IAddChild    
{
    private Canvas _innerCanvas;

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public UIElementCollection Children
    {
        get { return _innerCanvas.Children; }
    }

    public MyContainer()
    {
        this._innerCanvas = new Canvas();
        this.Content = _innerCanvas;

        this.Loaded += MyContainer_Loaded;
    }

    void MyContainer_Loaded(object sender, RoutedEventArgs e)
    {
        _innerCanvas.Height = this.ActualHeight;
        _innerCanvas.Width = this.ActualWidth;
    }

    void IAddChild.AddChild(object value)
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }

        UIElement uie = value as UIElement;

        if (uie == null)
        {
            throw new ArgumentNullException("value");
        }

        _innerCanvas.Children.Add(value as UIElement);
    }

    void IAddChild.AddText(string text)
    {
        ; 
    }
}

      

Where am I going wrong?

PS: please avoid responses like "don't use editor, only use XAML"; I need to make User Control available through a GUI.

+3


source to share


1 answer


I think you have not chosen the correct base class. There are certain points of extensibility in WPF that you must use for certain types of UI elements, and I am assuming the constructor is hardcoded into those classes.

Different types of interface elements:

  • Visuals: These are usually derived from FrameworkElement

    , and their purpose is to display something that the user would normally not interact with (like a text block).
  • Controls: These are what the user can interact with, such as buttons, checkboxes, text boxes, scrolls, etc. They usually come from Control

    or ContentControl

    .
  • Panels: Their purpose is to lay out other interface elements, Grid

    or StackPanel

    are examples. They all come from the base class Panel

    .
  • Controls: These usually provide selections for multiple items. ListBox

    , ComboBox

    and TreeView

    are examples for them. They all come from ItemsControl

    .

Another important thing: ContentControl

u ItemsControl

can display any object, not just those that can display themselves. They use the WPF data templating mechanism for this (by default, it is called ToString

on a non-rendered object and the resulting string is placed in TextBlock

).



As per your code, I would assume that you either want to implement a panel or a control. For panels, you should be aware of WPF 's Measure - Arrange - Render loop and how you can use it to arrange the children of a panel.

Implementing an item control is a bit tricky because essentially the item control uses items that wrap the actual content of each displayable (e.g. ListBoxItem

), a panel to lay out those items, an item container generator to dynamically create children, and of course you you can use styles and templates. Most item controls also include a scroll viewer. If you want to know more about item controls, I highly recommend you read the blog section Item Controls: A to Z by Dr. WPF.

I haven't tried it, but I'm pretty sure that if you choose the correct base class to extend then you can use your control correctly with the designer.

+2


source







All Articles