当前位置: 首页 > 知识库问答 >
问题:

WPF树视图,带有水平包装的叶子项目

秦学林
2023-03-14

新加入WPF的我正尝试使用TreeView,它提供的灵活性给我留下了难以置信的印象。

到目前为止,我的每个treeview项目都实现了一个扩展器,这是显示每个项目更详细信息并让标题仅显示摘要的好方法。但是,这不适合叶项目,并且浪费了屏幕空间——我的treeview中的每个叶项目(其中有许多)显示的数据量相对较小。

我想要为叶项目实现的是水平包装,而不是垂直列表。设想显示一个网格或(stackpanel),每个项目都显示在其自己的单元格/区域中,并根据可用水平空间的指示环绕到下面的行上。

例如

Level 1
  Level 2
     Level 3
      Leaf 1 | leaf 2 | leaf 3 | leaf 4
      Leaf 5 | leaf 6 | leaf 7 | leaf 8
      Leaf 9 .....

Level 1
  Level 2
     Level 3
       Leaf 1 | leaf 2|  ....

我已经为此寻找了很长时间——我读过关于树网格(这是我已经独立实现的)的书,也是一个很好的http://www.codeproject.com/Articles/17025/Custom-TreeView-Layout-in-WPF例子。这在某种程度上实现了我想要的,但没有实现项目的包装。

我的背景深植于WinForms中,并且由于缺乏WPF经验而受到限制(我喜欢迄今为止学到的东西)。我想做的事可行吗?

我不是要求一个样板,剪切和粘贴的解决方案,只是一些我可以探索的指针/资源/观点。

顺便说一句,由于我公司的吝啬本质,任何解决方案都必须是免费的。

非常感谢。

到目前为止,这是TreeView的xaml:

 <TreeView Name="tvMonitoredAlarms"  Margin="10,10,10,10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Auto" >
                <TreeView.ItemContainerStyle>
                    <Style TargetType="TreeViewItem">
                        <Setter Property="IsExpanded" Value="{Binding Expanded}"/>
                    </Style>
                </TreeView.ItemContainerStyle>


                <TreeView.Resources>

                    <!-- *****************************************************************************************************************
                     Server TreeView item 
                     ***************************************************************************************************************** -->
                    <HierarchicalDataTemplate DataType="{x:Type PAM:MonitoredServer}" ItemsSource="{Binding PLCs}">

                        <Border Margin="0" BorderBrush="{Binding AlarmPriority.BackColour, Converter={StaticResource PriorityBrush}}" 
                          Background="{Binding AlarmPriority.BackColour, Converter={StaticResource PriorityBrush}}">
                            <Border.Style>
                                <Style TargetType="{x:Type Border}">
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=OPCAlarmTriggered}" Value="True">
                                            <Setter Property="BorderThickness" Value="5"/>
                                            <Setter Property="CornerRadius" Value="3,3,3,3"/>
                                            <DataTrigger.EnterActions>
                                                <BeginStoryboard x:Name="FlashBorderSERVER" Storyboard="{StaticResource FlashBorder}"/>
                                            </DataTrigger.EnterActions>
                                            <DataTrigger.ExitActions>
                                                <StopStoryboard BeginStoryboardName="FlashBorderSERVER"/>
                                            </DataTrigger.ExitActions>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding Path=OPCAlarmTriggered}" Value="False">

                                            <Setter Property="BorderThickness" Value="1"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Border.Style>

                            <Expander Template="{StaticResource RevealExpanderTemp}"
                                OverridesDefaultStyle="True"
                                Header="{Binding ServerName}"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"

                                >

                                <Grid Margin="0,0,0,0" HorizontalAlignment="Stretch">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="50*"/>
                                        <ColumnDefinition/>

                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                    </Grid.RowDefinitions>
                                    <Label Margin="4,0,4,0" Grid.Row="0" Grid.Column="0">PLCs</Label>
                                    <Label Margin="4,0,4,0" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding NumberOfPLCs}" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" />
                                        <Label Margin="4,0,4,0" Grid.Row="1" Grid.Column="0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}">Monitored Alarms</Label>
                                        <Label Margin="4,0,4,0" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding NumberOfMonitoredAlarms}" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" />
                                        <Label Margin="4,0,4,0" Grid.Row="2" Grid.Column="0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}">Address</Label>
                                    <Label Margin="4,0,4,0" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding IPAddress}" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}"/>
                                    <Label Margin="4,0,4,0" Grid.Row="3" Grid.Column="0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}">Comment</Label>
                                    <Label Margin="4,0,4,0" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding Comment}" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}"/>

                                </Grid>

                            </Expander>
                        </Border>
                    </HierarchicalDataTemplate>
                    <!-- *****************************************************************************************************************
                     PLC TreeView item 
                     ***************************************************************************************************************** -->
                    <HierarchicalDataTemplate DataType="{x:Type PAM:MonitoredPLC}" ItemsSource="{Binding Areas}">
                        <Border Margin="0" BorderBrush="{Binding AlarmPriority.BackColour, Converter={StaticResource PriorityBrush}}" 
                        Background="{Binding AlarmPriority.BackColour, Converter={StaticResource PriorityBrush}}"
                                >
                            <Border.Style>
                                <Style TargetType="{x:Type Border}">

                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=OPCAlarmTriggered}" Value="True">
                                            <Setter Property="BorderThickness" Value="5"/>
                                            <Setter Property="CornerRadius" Value="3,3,3,3"/>
                                            <DataTrigger.EnterActions>
                                                <BeginStoryboard x:Name="FlashBorderPLC" Storyboard="{StaticResource FlashBorder}"/>
                                            </DataTrigger.EnterActions>
                                            <DataTrigger.ExitActions>
                                                <StopStoryboard BeginStoryboardName="FlashBorderPLC"/>
                                            </DataTrigger.ExitActions>

                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding Path=OPCAlarmTriggered}" Value="False">

                                            <Setter Property="BorderThickness" Value="1"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Border.Style>
                            <Expander Template="{StaticResource RevealExpanderTemp}"
                                OverridesDefaultStyle="True"
                                Header="{Binding Name}"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                >

                                <Expander.Background>
                                    <LinearGradientBrush ColorInterpolationMode="ScRgbLinearInterpolation" StartPoint="0,0.5" EndPoint="1,0.5">

                                        <GradientStop Color="{Binding AlarmPriority.BackColour, Converter={StaticResource PriorityBrush}}" Offset="0"/>

                                        <GradientStop Color="DarkKhaki" Offset="0.75"/>

                                    </LinearGradientBrush>
                                </Expander.Background>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="200"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                    </Grid.RowDefinitions>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="0" Grid.Column="0">Areas</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding NumberOfAreas}" />
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="1" Grid.Column="0">Monitored Alarms</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding NumberOfMonitoredAlarms}" />
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="2" Grid.Column="0">Device</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding Device}" />
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="3" Grid.Column="0">Model</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding Model}" />
                                </Grid>
                            </Expander>
                        </Border>

                    </HierarchicalDataTemplate>
                    <!-- *****************************************************************************************************************
                     Area TreeView item 
                     ***************************************************************************************************************** -->
                    <HierarchicalDataTemplate DataType="{x:Type PAM:MonitoredArea}" ItemsSource="{Binding Alarms}">
                        <Border Margin="0" BorderBrush="{Binding AlarmPriority.BackColour, Converter={StaticResource PriorityBrush}}"
                        Background="{Binding AlarmPriority.BackColour, Converter={StaticResource PriorityBrush}}">

                            <Border.Style>
                                <Style TargetType="{x:Type Border}">

                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=OPCAlarmTriggered}" Value="True">
                                            <Setter Property="BorderThickness" Value="5"/>
                                            <Setter Property="CornerRadius" Value="3,3,3,3"/>
                                            <DataTrigger.EnterActions>
                                                <BeginStoryboard x:Name="FlashBorderAREA" Storyboard="{StaticResource FlashBorder}"/>
                                            </DataTrigger.EnterActions>
                                            <DataTrigger.ExitActions>
                                                <StopStoryboard BeginStoryboardName="FlashBorderAREA"/>
                                            </DataTrigger.ExitActions>

                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding Path=OPCAlarmTriggered}" Value="False">

                                            <Setter Property="BorderThickness" Value="1"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Border.Style>
                            <Expander Template="{StaticResource RevealExpanderTemp}"
                                OverridesDefaultStyle="True"
                                Header="{Binding OPCArea.DBArea.fldDescription}"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                >
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition/>
                                        <ColumnDefinition Width="100"/>
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition/>
                                    </Grid.RowDefinitions>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="0" Grid.Column="0">Monitored Alarms</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding NumberOfMonitoredAlarms}" />

                                </Grid>
                            </Expander>
                        </Border>
                    </HierarchicalDataTemplate>


                    <!-- *****************************************************************************************************************
                     Alarm TreeView item 
                     ***************************************************************************************************************** -->
                    <DataTemplate DataType="{x:Type PAM:MonitoredAlarm}">
                        <Border Name="AlarmBorder"
                                BorderBrush="{Binding AlarmPriority.BackColour, Converter={StaticResource PriorityBrush}}" 
                                Background="{Binding AlarmPriority.BackColour, Converter={StaticResource PriorityBrush}}" 
                                >
                            <Border.Style>
                                <Style TargetType="{x:Type Border}">

                                     <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=OPCAlarmTriggered}" Value="True">
                                            <Setter Property="BorderThickness" Value="5"/>
                                            <Setter Property="CornerRadius" Value="3,3,3,3"/>

                                            <DataTrigger.EnterActions>
                                                <BeginStoryboard x:Name="FlashBorder" Storyboard="{StaticResource FlashBorder}"/>
                                            </DataTrigger.EnterActions>
                                            <DataTrigger.ExitActions>
                                                <StopStoryboard BeginStoryboardName="FlashBorder"/>
                                            </DataTrigger.ExitActions>

                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding Path=OPCAlarmTriggered}" Value="False">

                                            <Setter Property="BorderThickness" Value="1"/>
                                        </DataTrigger>
                                    </Style.Triggers> 
                                </Style>
                            </Border.Style>

                            <Expander Template="{StaticResource RevealExpanderTemp}"
                            OverridesDefaultStyle="True"
                            Header="{Binding Description}"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Top"
                            Width="400"
                            >

                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="200"/>
                                        <ColumnDefinition/>
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                        <RowDefinition/>
                                    </Grid.RowDefinitions>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="0" Grid.Column="0">Current Value</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding OPCAlarm.OPCValue}" />


                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="1" Grid.Column="0">Priority</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding AlarmPriority.DBPriority.fldName}" />
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding TagName}" />
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="4" Grid.Column="0">Address</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding Address}" />
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="5" Grid.Column="0">Scan rate</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="5" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding ScanRate}" />
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding LastActive}" />
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="3" Grid.Column="0">Activity</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding Activity}" />
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="4" Grid.Column="0">Comment</Label>
                                    <Label Margin="4,0,4,0" Foreground="{Binding AlarmPriority.ForeColour, Converter={StaticResource PriorityBrush}}" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right" Content="{Binding DBMonitoredAlarm.fldComment}" />
                                </Grid>
                            </Expander>
                    </Border>
                </DataTemplate>
            </TreeView.Resources>
        </TreeView>

共有1个答案

姜乐家
2023-03-14

好的,我通过将树管中显示的数据重组为“行”的集合来解决这个问题,其中每行可以容纳多达10个值。然后将此集合绑定到一个数据网格(最多可以有10列),该数据网格显示在树视图中的数据模板中。

不完全完美,但它符合我的需要。

 类似资料:
  • 我试图实现带有水平滚动的,所以我使用了带有水平方向的。问题是,我使用2种不同类型的项目填充RecyclerView,具有不同的高度。这是我对项目使用的布局: 这是包含的布局,基本上是这样的: 我使用的是一个,我只是更改了两个子视图的可见性。 我希望得到的结果是: 但我得到的是这个;使用第二种物品的高度将CardView切成两半: 我看到了这个帖子,和我的问题差不多,它推荐使用,于是,我尝试实现:

  • 我正在学习WPF,我想我缺少一些用户控件。我将尝试用例子来演示。基本上,假设我有一个treeview,我想将标签文本绑定到treeview selectedItem。这似乎很简单: 现在,为了使事情复杂化,我将在混合中添加一个用户控件。用户控件基本上是网格中的TreeView: 其目的是用usercontrol替换上面使用的vanilla treeview,并根据所选内容更改标签内容。所以,我试着

  • 我想做的从右到左滚动与我猜将是一个recylcer视图,但不确定是否是这个。我只是需要有人给我指明正确的方向。我想我需要一个内部布局的回收视图。 如果有人能指点我在哪里找到答案,我会变得很伟大!

  • 我想要达到的目标 项目视图应占据项目的整个高度 可能是项目的高度小于回收视图中最高项目的高度,在这种情况下,它应该像上面的截图一样粘在顶部。 我遇到的虫子 正如上面的截图所示,视图正在被截断。 到目前为止我都试过了 起初,我在回收视图上使用wrap_content,现在它得到了支持。当当时屏幕上可见的视图都不是最高的时,它就不起作用了。这在视图层次结构的布局中是有意义的。如果高度依赖于任何数据,那

  • 我正在尝试使用 和 从维基百科中重现如下所示的概率树图。以下是我的开始, 它随机放置节点,以数字方式标记它们,并且边缘没有标签: 相反,我需要重新组织并标记边和节点,就像这样,只是将节点标签放在圆圈内:

  • 我有一个树状视图,其中有可选择的项,以及可能触发某些代码操作的子项。单击子项时,应执行操作,但父项必须保留/成为选定项。 我面临的问题是项目没有被正确取消选择,导致在树视图中选择多个项目。 以下是treeview的xaml: clsBindingDebugger除了调试打印转换的值并传递转换和转换回值之外什么也不做。 接下来是TreeviewItem类的略为缩短的版本 最后我触发事件MyTreev