在继承自ItemsPanel的用户控件中组合Viewbox,Canvas,ItemsPanelTemplate和ItemsPresenter

问题描述 投票:0回答:2

我想扩展ItemsPanel,以便我可以显示一个“分层”的视觉结构,其中我有一个具有已知大小和大量叠加的“框架”,类似于制图或插图应用程序。

我遇到的问题是找出如何组合事物,以便一切按预期工作。到目前为止我做了什么:

  • 创建了一个继承自ItemsControl的控件;
  • 在控制内,放一个含有ViewboxItemsPresenter
  • 在控件的Resources中,创建了一个以自己的类型为目标的Style,将ItemsPanel设置为一个由Canvas组成的ItemsTemplate。

所以我希望,在Live Tree Inspection中,我应该看到,在嵌套结构中:

  • LayerContainer(我的控件的类名) 视框 ItemsPresenter 帆布 项目1 项目2

相反,我看到的是:

  • LayerContainer 边界 ItemsPresenter 帆布 视框 项目1 项目2

所以问题是ViewBox包含在Canvas中,与渲染项一起。

那么我的问题是:如何以嵌套顺序为ItemsPresenter-> Viewbox-> Canvas-> Items的方式构建我的LayerContainer控件?

这是我的控制(名称实际上不是LayerContainer

<ItemsControl x:Class="Miotec.PressureMapping.UserControls.BaroLayerContainer"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
            xmlns:local="clr-namespace:Miotec.PressureMapping.UserControls"
            mc:Ignorable="d" 
            d:DesignHeight="450" d:DesignWidth="800">

    <ItemsControl.Resources>
        <Style TargetType="local:BaroLayerContainer">
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <Canvas Width="{Binding Parametros.Colunas}"
                                Height="{Binding Parametros.Linhas}"
                                IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ItemsControl.Resources>

    <Viewbox Stretch="Uniform" x:Name="container">
        <ItemsPresenter
            Width="{Binding ActualWidth, ElementName=container}"
            Height="{Binding ActualHeight, ElementName=container}"/>
    </Viewbox>
</ItemsControl>
wpf xaml wpf-controls itemscontrol itemspresenter
2个回答
0
投票

如果你想要一个如何做到这一点的工作实例,那么看看我的Perfy editor on GitHub,相关部分是在the MainWindow.xaml file。它还展示了如何实现缩放和滚动(如果你想支持两者,那么你实际上不需要ViewBox,只需要一个ScrollViewer父项和ItemsControl上的LayoutTransform)。

要回答您的问题,每个项目都包含在ContentPresenter中,诀窍是在此父项目上设置您的Canvas位置。 ItemsControl公开了ItemContainerStyle,它允许你这样做:

<ItemsControl.ItemContainerStyle>
    <Style TargetType="{x:Type ContentPresenter}">
        <Setter Property="Canvas.Left" Value="{Binding X}" />
        <Setter Property="Canvas.Top" Value="{Binding Y}" />
    </Style>
</ItemsControl.ItemContainerStyle>

特别要注意的是,你不需要自己明确声明一个ItemsPresenter,这是因为你已经开始使用ItemsControl了。只需将你的ItemsPanel设置为Canvas,通过ContentPresenter设置ItemContainerStyle的样式,然后使用DataTemplates和/或触发器指定集合项本身的外观。


0
投票

经过一些思考和谷歌搜索,我意识到我可以“覆盖”我的控制的Template属性,用ControlTemplate我将把Viewbox作为root,并在其中,ItemsPresenter。然后在渲染时,每个项目将被放置在包含ItemsPanelTemplateCanvas中,分配给ItemsPanel属性。

以下是最终的工作表格。解决方案原则是除了Template属性(对于Canvas)还设置ItemsPanel属性(对于ViewBox)。

<ItemsControl x:Class="Miotec.PressureMapping.UserControls.BaroLayerContainer"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
            xmlns:local="clr-namespace:Miotec.PressureMapping.UserControls"
            mc:Ignorable="d" 
            d:DesignHeight="450" d:DesignWidth="800">

    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <Grid x:Name="container">
                <Viewbox Stretch="Uniform" 
                        Width="{Binding ActualWidth, ElementName=container}"
                        Height="{Binding ActualHeight, ElementName=container}">
                    <ItemsPresenter/>
                </Viewbox>
            </Grid>
        </ControlTemplate>
    </ItemsControl.Template>

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Width="{Binding Parametros.Colunas}"
                    Height="{Binding Parametros.Linhas}"
                    IsItemsHost="True"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

</ItemsControl>
© www.soinside.com 2019 - 2024. All rights reserved.