【问题标题】:Style me an ItemsControl subclass please - stuch with ItemsPresenter请为我设置一个 ItemsControl 子类 - 使用 ItemsPresenter
【发布时间】:2019-01-11 14:40:42
【问题描述】:

我有一个从ItemsControl 继承的控件,称为WorkSheet

public sealed class WorkSheet : ItemsControl {

它的元素被强制为WorkTiles:

    /// <inheritdoc />
    protected override bool IsItemItsOwnContainerOverride(object item) {
        return (item is WorkTile);
    }

    /// <inheritdoc />
    protected override DependencyObject GetContainerForItemOverride() {
        return new WorkTile();
    }

到目前为止 - 非常好。我希望WorkSheet 使用Canvas 来呈现WorkItems,位置由覆盖ArrangeOverride 确定,它被调用并正确确定位置。确切的位置正在覆盖中确定。不过,我对造型很迷茫。我根本无法让这些项目出现。在 Generic.xaml 中,我定义了样式。它们有效,但不是应有的效果:

<Style TargetType="{x:Type local:WorkSheet}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Border>
                    <ItemsPresenter />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <ContentPresenter />
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

在这里,几乎在表示树中,ItemsPresenter 是最低的元素。 ItemsPresenter 的子元素永远不会出现。我还尝试将CanvasIsItemsHost="true" 一起放入ControlTemplate - 再次,没有项目。有人知道我在这里做错了什么吗?

同样,作为解释 - 我在表单上的按钮处理程序中放置了一个断点,并使用 Visualizer 来查看可视化树。我得到的层次结构是:

WorkSheet -&gt; Border -&gt; ItemsPresenter ... 下面什么都没有。

显然这意味着使用了ControlTemplate,但从未调用过ItemsPanel

【问题讨论】:

    标签: c# wpf styles itemscontrol


    【解决方案1】:

    在您的 ControlTemplate 中也放置一个 TargetType:

    <ControlTemplate TargetType="{x:Type local:WorkSheet}">
    

    不工作;)

    更新 2:

    我在一个副项目中复制了你的东西,你有两个问题:

    第一个问题是您 Style 中的 ItemTemplate 设置器,它将触发 StackOverflow 异常(多么讽刺;))。删除 ContentPresenter,删除整个模板或使用密钥。

    第二个问题是GetContainerForItemOverride 方法。删除这个方法会给我屏幕上的东西!

    这是我的代码:

    public sealed class WorkSheet : ItemsControl
    {
        /// <inheritdoc />
        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return (item is WorkTile);
        }
    
    }
    

    以及带有样式的Window的xaml:

    <Window x:Class="WpfApplication8.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:WpfApplication8="clr-namespace:WpfApplication8"
        Title="Window1" Height="300" Width="300">
    
        <Window.Resources>
            <Style TargetType="{x:Type WpfApplication8:WorkSheet}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate >
                            <Border>
                                <ItemsPresenter />
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Setter Property="ItemsPanel">
                    <Setter.Value>
                        <ItemsPanelTemplate>
                            <Canvas />
                        </ItemsPanelTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    
        </Window.Resources>
    
        <Grid>
            <WpfApplication8:WorkSheet x:Name="sheet" />
        </Grid>
    </Window>
    

    【讨论】:

    • 不起作用 - 相同的行为。还有其他想法吗?更重要的是:关于为什么需要此 TargetType 的任何参考,因为 ControlTemplate 恕我直言,已经通过样式绑定到一种特定类型。只是想理解。
    • 是的,开始工作了。仍然不明白到底出了什么问题;)我尝试了 - 现在再次添加我自己的代码(到类中)。
    • 大部分情况下都能正常工作 - 谢谢。现在唯一的问题 - 当我覆盖 ArrangeOverride 时,所有客户端项目都会消失。如果 ArrangeOverride 只读取:protected override Size ArrangeOverride(Size finalSize) { return finalSize; }。没有 ArrangeOverrride 覆盖 - 项目出现。有什么想法吗?
    • 当你覆盖 ArrangeOverride 时,你不应该像那样返回 finalSize。该方法期望您计算大小,当大小为无限时,您将看不到任何东西。最好返回 new Size(Width, Height) 或调用 base.ArrangeOverride(finalSize),让他们为你计算!希望这能澄清一点;)
    • 终于明白了。谢谢。似乎需要 ArrangeOverride 基本调用。从未有过 Infinite,但除非 ArrangeOverride 调用它的“基础”实现,否则它仍然是不可见的。
    猜你喜欢
    • 2011-04-13
    • 2011-09-05
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    相关资源
    最近更新 更多