2015-05-25 24 views
2

我需要有一个自定义面板充当画布,但确实是一个ScrollViewer中里面的画布。用户应该能够像在画布中一样添加控件;我需要ScrollViewer包装来处理缩放和平移行为。WPF - 封装定制画布ScrollViewer中

于是,我开始写的控制:

[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; 

     _innerCanvas.Height = this.ActualHeight; 
     _innerCanvas.Width = this.ActualWidth; 
    } 

    void IAddChild.AddChild(object value) 
    { 
     _innerCanvas.Children.Add(value as UIElement); 
    } 

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

,但它不工作。如果我尝试在XAML中使用它

<Controls:MyContainer> 
    <TextBlock Height="92" Canvas.Left="324" TextWrapping="Wrap" Text="TextBlock 1" Canvas.Top="267" Width="284"/> 
    <TextBlock Height="92" Canvas.Left="462" TextWrapping="Wrap" Text="TextBlock 1" Canvas.Top="267" Width="284"/> 
</Controls:MyContainer> 

孩子们不可见。

出了什么问题?

回答

2

您在Ctor中将画布的大小设置为ActualWidthActualHeight,但它们尚未在此处初始化。 ActualWidthActualHeight时,呈现在屏幕上的控制才有意义。尝试订阅的ScrollViewer的Loaded事件,并更改画布大小,则:

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

    this.Loaded += ScrollViewer_Loaded; 
} 

public void ScrollViewer_Loaded(object sender, EventArgs e) 
{ 
    _innerCanvas.Height = this.ActualHeight; 
    _innerCanvas.Width = this.ActualWidth; 
} 
+0

是的,你说得对,谢谢。但还有另一个问题。 MyContainer控件内的控件是固定的。在XAML编辑器中,我无法用鼠标移动它们。 – rPulvi

+0

我不太确定。我尽可能避免设计师。只需手动更新值。最好是这么写的XAML这样的,因为设计者必须增加很多额外的代码,你并不需要,如果你要的话,尽量设计在不同的画布控件,比复制代码到你的倾向。 – CKII

+0

我同意你的看法,但这种控制的主要目标是通过XAML图形编辑器中使用。你知道是什么让孩子们在容器中“移动”吗? – rPulvi