0

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

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

  • 创建了一个继承自的控件ItemsControl
  • 在控件内部,放置一个Viewbox包含一个ItemsPresenter
  • 在控件的资源中,创建了一个针对其自身类型的样式,将 设置ItemsPanel为由Canvas.

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

  • LayerContainer(我的控件的类名)
    • 视图框
      • 项目演示者
      • 帆布
        • 项目1
        • 项目2

相反,我看到的是:

  • 层容器
    • 边界
      • 项目演示者
      • 帆布
        • 视框
        • 项目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>
4

2 回答 2

0

如果您想要一个如何执行此操作的工作示例,请查看我在 GitHub 上的 Perfy 编辑器,相关部分位于MainWindow.xaml 文件中。它还展示了如何实现缩放和滚动(如果你想同时支持这两者,那么你实际上不需要一个 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和/或触发器来指定集合项目本身的外观。

于 2019-02-11T22:20:47.423 回答
0

经过一番思考和谷歌搜索,我意识到我可以“覆盖”Template我的控件的属性,我可以在ControlTemplate其中放置Viewbox根目录,并在其中放置 ItemsPresenter。然后在渲染时,每个项目将被放置在ItemsPanelTemplate包含Canvas分配给ItemsPanel属性的 , 中。

所以下面是最终的工作形式。解决方案的原则是除了属性(用于画布)之外,还设置Template属性(用于 ViewBox )。ItemsPanel

<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>
于 2019-02-12T12:44:33.300 回答