I have a custom control (let's say MyContainer) that simply is a ScrollViewer with a Canvas inside.
I'm able to add controls to MyContainer like in a Canvas but in XAML designer this controls aren't movable like in a normal Canvas; they can't 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 wrong?
PS: please avoid replies like "don't use editor, use XAML code only"; I need to make a User Control usable via graphic interface.
I think that you did not choose the correct base class. In WPF there are certain extensibility points that you should use for certain types of UI elements and I guess that the designer is hard-wired to these classes.
The different types of UI Elements are:
FrameworkElement and their purpose is to display something that the user normally does not interact with (e.g. a text block).Control or ContentControl.Grid or StackPanel are examples. They all derive from the Panel base class.ListBox, ComboBox, and TreeView are examples for them. All of them derive from ItemsControl.Another important thing is that ContentControls and ItemsControls can display any object, not only those that can render themselves. They use the WPF Data Templating mechanism for that (the default is calling ToString on a non-renderable object and putting the resulting string in a TextBlock).
According to your code, I would assume that you either want to implement a panel or an items control. For panels, you should know about the Measure - Arrange - Render cycle of WPF and how you can use it to layout the panel's children.
Implementing an items control is a little bit harder because essentially an items control uses items that wrap the actual content of each displayed object (e.g. ListBoxItem), a panel to layout these items, an items container generator to dynamically create the child items, and of course you can use styles and templates. Most of the items controls also incorporate a scroll viewer. If you want to learn more about items controls, I strongly encourage you to read the "Items Controls: A to Z" blog series by Dr. WPF.
I haven't tried it out but I'm sure if you choose the correct base class to extend from, then you can use your control with the designer properly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With