仅为第一个子

时间:2016-02-24 18:28:18

标签: c# wpf

所以问题是我创建了一个自定义Control,其中包含3个来自FrameworkElement的其他控件:

class TextArea : Control {
    private List<LocalViewBase> views;
    private Views.TextView.View textView;
    private Views.CaretView.View caretView;
    private Views.SelectionView.View selectionView;

    protected override int VisualChildrenCount => views.Count;

    protected override Visual GetVisualChild(int index) => views[index];

    public TextArea() {
        views = new List<LocalViewBase>();

        SetViews();
    }

    private void SetViews() {
        textView = new Views.TextView.View() { Margin = new Thickness(EditorConfiguration.GetTextAreaLeftMargin(), 0, 0, 0) };
        textInfo = new LocalTextInfo(textView);
        selectionView = new Views.SelectionView.View(textInfo) { Margin = new Thickness(EditorConfiguration.GetTextAreaLeftMargin(), 0, 0, 0) };
        caretView = new Views.CaretView.View(textInfo) { Margin = new Thickness(EditorConfiguration.GetTextAreaLeftMargin(), 0, 0, 0) };

        foreach (var view in new LocalViewBase[] { selectionView, textView, caretView }) {
            views.Add(view);

            AddVisualChild(view);
            AddLogicalChild(view);
        }
    }
}

public abstract class LocalViewBase : FrameworkElement { }

LocalViewBase目前是源自FrameworkElement的空类。 我现在正在处理的问题是,只有最早添加的孩子的OnRender被调用 - 在这种情况下是selectionView - 并且只有它以适当的边距绘制。我从这里尝试了@ devhedgehog的答案:WPF - Visual tree not used for drawing?但它并没有为我做的伎俩。即使我扩展Panel类而不是Control并使用其Children集合而不是对AddVisualChild()AddLogicalChild()的调用,仍然无法绘制视图有适当的保证金。我也试过像InvalidateWhatever()这样的方法,但也没有帮助。

可能其他视图没有绘制正确的边距,因为它们都堆叠在一起,WPF“认为”只有selectionView是可见的,所以实际的问题是 - 怎么做我说服它不这么认为? :)

1 个答案:

答案 0 :(得分:0)

这个问题的解决方案非常简单。我必须扩展StackPanel类并覆盖ArrangeOverride方法(对于要放在x,y = 0,0上的每个子项)。

public abstract class StackablePanel : StackPanel {
    protected override Size ArrangeOverride(Size arrangeSize) {
        foreach (var child in Children) {
            var uiElement = (UIElement)child;
            var rcChild = new Rect(0, 0, Width, Height);

            uiElement.Arrange(rcChild);
        }

        return arrangeSize;
    }
}

在我以前的一个解决此问题的方法中,我扩展了Panel类,但这还不够 - ArrangeOverride的默认实现并没有放置UIElement&按照我的意愿,并没有将正确的Size实例传递给孩子的Arrange方法。

现在,当我的TextArea类扩展了这个时,它的每个子视图都被正确绘制,并且调用了它的OnRender方法。