基本上它是一个瓷砖视图,以带状网格显示,在调整窗口大小时动态更改列数。这些项目是可选择的。这些可能看起来像图片,但它们只是Unicode字符。
我已经创建了一个自定义对象列表,并成功地将列表绑定到ListBox控件。当然,这给了我一个垂直堆叠的字符列表。
所以我用Google搜索了一些,发现我可以为列表框设置自定义ItemsPanelTemplate:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Margin="0"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
为了设置图块的边框和大小,我还添加了一个ItemTemplate:
<ListBox Margin="0,0,0,0" Padding="0,0,0,0" Grid.Row="0" Grid.Column="0" x:Name="tw"
SelectionChanged="tw_SelectionChanged"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Margin="0,0,0,0"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Label
Padding="0,0,0,0"
Margin="0,0,0,0"
Width="50"
Height="50"
FontSize="20"
Background="White"
HorizontalAlignment="Left"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
BorderThickness="1"
BorderBrush="Black"
Content="{Binding Path=LiteralString}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
第一个问题是,正如你所看到的,瓷砖之间有空间我无法摆脱。您会在标记中注意到我尝试尽可能手动将边距和填充设置为0。空间仍在那里。
第二个问题是,你无法真正看到选择了哪个项目。选择底部的第3个字符和右侧的第2个字符,但标签覆盖蓝色。你只能在角色左边的空白处看到它。我不知道如何解决这个问题。
另一个潜在的问题是表现。该视图最终将具有过滤器,但是当所有过滤器都关闭时,有大约6500个项目要显示。当我只有一个基本的ListBox时,应用程序在运行时占用了大约28MB的RAM。当我使用WrapPanel添加ItemsPanelTemplate时,内存使用量跃升至约136MB。当我添加带有标签的ItemTemplate时,内存使用率跃升至183MB,更糟糕的是,窗口现在需要更长时间才能加载。
我已经尝试用TextBlocks替换标签,因为我读过它们的重量要轻得多。事情变得更快,内存使用量回落到130MB左右,但TextBlocks并不好。我无法将文字置于其中,或给它们边框。正如您在屏幕截图中看到的那样,所选项目搞砸了:
当然,我的计算机速度很慢,而且183MB不是终身的,但它仍然有点低效。我打算在这个应用程序中添加更多功能,如果这一件事占用了大量的RAM,那么最终的应用程序可能会成为一个无法使用的资源吸血鬼。另外,我相信我模仿的应用程序也是用.NET编写的(虽然我不确定它是否是WPF)并且在显示视图时只使用17.5MB的RAM。
还有另一种方法可以做到这一点,既有效又更容易定制?
谢谢。
我找到了一种稍微好一些的方法。我完全删除了ItemTemplate,而是使用ItemContainerStyle:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Setters>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Width" Value="50"/>
<Setter Property="Height" Value="50"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True" >
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Background" Value="SteelBlue" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
这会产生更好的效果。瓷砖之间没有可见的空间,我可以自定义选定和取消选择的瓷砖的外观。
我唯一不知道该怎么办的是一条厚度为1像素的边框线。我得到两条厚度为1的线,导致厚度为2.我尝试将边距和填充设置为0和-1。没运气。奇怪的是,将BorderBrush设置为Black并将BorderThickness设置为0.5不会产生厚度为1的组合黑线,而是产生厚度为2的灰线。
与使用标签时相比,内存使用率略有下降至约150MB,但加载时间仍然很恶劣,因此我仍在寻找更好的解决方案。
我在边缘玩了一段时间,我终于把它钉了起来。我通过将ListBoxItem的边距设置为-0.5得到了正确的边框厚度,将图块稍微压缩在一起。我想保持这个问题,所以希望有人会提出一个更有效的解决方案。 UI一旦运行就会响应,但加载时间很糟糕。在使用我的应用程序期间,将重复填充ListBox,因为调整了过滤器并进行了查询。我希望这很快发生。此外,在我看来,内存使用率也不必要地高。
答案 0 :(得分:0)
由于我没有足够的代表发表评论,会尝试回答,或者至少指出正确的方向。 1)厚度为2的原因是相邻边界连接各自的厚度。并且你使用-0.5边距使它们交叉,使得结果厚度为1.相反,你可以尝试设置右边和底边的边框厚度,如:
<Setter Property="BorderThickness" Value="0,0,1,1"/>
这意味着LeftSide = 0,Top = 0,RightSide = 1,Bottom = 1 thick。所以最左边的项目不会有左边框,最顶层的项目不会有顶边框。因此,相邻的边界不会使其厚度增加一倍。
2)并且因为内存使用过多而整体性能下降。当您使用WrapPanel for ItemsPanel时,您将丢弃UI虚拟化。因为通常非UI计算不需要花费太多时间首先考虑UI性能。尝试加载您的数据并在没有UI的情况下进行计算,我认为区别很明显。 我建议你为ListBox ItemsPanel使用某种VirtualizingWrapPanel。就个人而言,我使用这个更有经验的编码员提出的更正: