【问题标题】:When is DataTemplate used in ContentControl and ItemsControl?什么时候在 ContentControl 和 ItemsControl 中使用 DataTemplate?
【发布时间】:2014-02-21 12:15:51
【问题描述】:

我创建的 WPF 控件继承了 FrameworkElement 类。其中一个是这样完成的:

[ContentProperty("Children")]
public class ItemsElement : FrameworkElement
{
    public ItemsElement()
    {
        Children = new UIElementCollection(this, this);
    }

    public UIElementCollection Children { get; private set; }

    protected override int VisualChildrenCount
    {
        get
        {
            if (Children != null)
            {
                return Children.Count;
            }

            return 0;
        }
    }

    protected override Visual GetVisualChild(int index)
    {
        return Children[index];
    }

    protected override IEnumerator LogicalChildren
    {
        get
        {
            if (Children != null)
            {
                return Children.GetEnumerator();
            }

            return EmptyEnumerator.Instance;
        }
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        return availableSize;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        return finalSize;
    }
}

我希望这段代码的元素不是 2D-UI 元素。我重写了 Measure 和 Arrange 方法,这样它就不会计算孩子的大小。这是我想要的行为,因为这些计算繁重且无用。

问题是,如果我将 ContentControls 和 ItemsControls 放在我的 ItemsElement 类的子项中(通过 XAML),这些控件似乎不会使用我在资源中为它们定义的 DataTemplate 从 Content/ItemsSource 生成它们的 Visual 子项。

如果我在 MeasureOverride 方法的开头添加此代码,它确实有效:

foreach (UIElement child in Children)
{
    child.Measure(availableSize);
}

我不明白为什么......

你有什么想法吗?

谢谢!

【问题讨论】:

    标签: wpf


    【解决方案1】:

    问题真的是你为什么要扩展一个你不想要的行为的类?这里的答案太长了,但你可以在Control Authoring Overview页面上完整阅读MSDN。但简而言之,我只能假设您扩展了错误的类。也许你甚至不需要扩展任何类。

    在 WPF 中,有 许多 替代方法来编写新控件。通常唯一真正需要这样做的是为无法通过其他方式组合的独特控件执行一些特殊的自定义绘图。正如链接页面所说,WPF 使您能够通过使用其丰富的内容模型、样式、模板和触发器来自定义现有控件。进一步的继续:

    从 UserControl 或 Control 派生的控件依赖于组合现有元素。对于许多情况,这是一个可接受的解决方案,因为从 FrameworkElement 继承的任何对象都可以在 ControlTemplate 中。但是,有时控件的外观需要的不仅仅是简单元素组合的功能。对于这些场景,基于 FrameworkElement 构建组件是正确的选择。

    最后,MeasureOverrideArrangeOverride 方法需要正确实现,FrameworkElement 才能呈现其项目。您只需要查看 MSDN 即可找到这些基本信息。来自FrameworkElement.MeasureOverride Method 页面:

    您的实现应执行以下操作:
    1.迭代元素的特定子元素集合,这些子元素是布局的一部分,对每个子元素调用 Measure。

    FrameworkElement.ArrangeOverride Method 页面:

    父元素应在每个子元素上调用 Arrange,否则子元素将不会被渲染。

    请阅读链接页面以获取更多信息,以后请在 MSDN 中查找有关您的问题控制、方法、事件等的信息。在这里提问之前。


    更新>>>

    作为对您有些冒犯性评论的回应,我可以看到您确实有正当理由扩展 FrameworkElement 类,但这不会改变任何事情。你你已经阅读了我向你展示的所有页面,但由于某种原因,你没有遵循关于你拥有什么的明确说明 /em> 正确呈现项目。

    没有必要回答您关于DataTemplate 的问题以及它的确切呈现时间,因为它与您的问题无关。您的问题仅仅是因为您没有按照课堂上 MSDN 上的说明进行操作。就是这样。您可以检查一下这是否正确的一件事就是这个。

    如果您在运行应用程序时看到集合中对象类型的全名,那么您的DataTemplate 没有被应用是有问题的。但是,如果您没有看到任何项目,那么您的渲染就有问题,这仅仅是因为您没有正确实现这两个基本方法。

    【讨论】:

    • 请参阅this post of mine 了解我为什么要扩展 FrameworkElement 而不是其他任何东西。您告诉我阅读 MSDN 文档,我已经阅读并看到了您“解释”的内容,但您没有回答我的问题:ContentControl 和 ItemsControl 何时使用 DataTemplate?也就是说,在 Measure 方法的实现内部,这对我来说是一个黑盒子。如果没有帮助,请不要说什么。
    • 小心你的cmets。当任何用户花时间回答问题时,采取这种态度是不合适的。如果你再看看你的问题,你会发现你实际上问了这个关于MeasureOverride方法的问题:我不明白为什么......你有什么想法吗? 这就是我要回答的问题,所以也许您需要编辑您的问题,以便更清楚地了解您实际上想知道什么,而不是侮辱本网站的高级成员。
    • 是的,对不起。你的回答“阅读文档,小菜鸟”让我有点生气。但我意识到原来的问题写得不好......所以,再次抱歉!
    • 所以现在,要走得更远:我知道我必须正确实现 MeasureOverride 和 ArrangeOverride 方法才能使 DataTemplates 工作。关键是我不希望系统运行 Measure 和 Arrange 算法,因为它们在我的特殊情况下太昂贵且无用(我有一个沉重的 3d 场景图,它没有显示在 UI 中)。也许我应该为此提出另一个问题?
    • 确实听起来值得提出一个新问题,请提供尽可能多的相关信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-25
    • 2013-11-11
    • 2016-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多