【问题标题】:FrameworkElement's OnRender method is called only for the first childFrameworkElement 的 OnRender 方法只为第一个孩子调用
【发布时间】:2016-02-26 05:16:12
【问题描述】:

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

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 是可见的,所以实际的问题是 - 我如何说服它认为不是吗? :)

【问题讨论】:

  • Aaaand 为什么是 -1 和接近投票?
  • 所以您确实尝试过覆盖VisualChildrenCountGetVisualChild()
  • 对不起,我没有在我的问题中发布它,但是是的 - 两者都被覆盖了。我将编辑我的问题。
  • 我们应该退后一步,确定您在这里实际想要完成的工作。 WPF 的 TextBox 有没有你想要它做的事情?像这样在 C# 中编写控件很讨厌。
  • Wpf 的TextBox 不适合我的需要。我正在编写一个自定义代码编辑器控件——比如 AvalonEdit。我对其中缺少的一些功能不满意,我认为自己创建这样的东西会很有趣。我没记错,不过这个边距问题真的很烦人。

标签: c# wpf


【解决方案1】:

这个问题的解决方案非常简单。我必须扩展 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 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 2017-03-11
    • 1970-01-01
    • 2022-10-19
    • 2018-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多