c# - 将一个 WPF ListView 的项目与相对于另一个 ListView 中项目的最终布局的位置对齐
问题描述
根据评论,我想了一种方法来简化我的问题:嵌套在右侧列中的用户控件内的任意点将在布局和渲染后最终到达某个最终位置。我想找出那个点是什么,并调整左列上元素的高度,使其在那个 Y 坐标上结束。我想对所有盒子重复这个过程。
我制作了一个 WPF 窗口来显示解码的串行数据。我有一个带有字节块的左侧列,以及一个带有位字段块的右侧列。位字段可以是 1 到 16 位长,并且不一定与字节边界对齐。但是我希望字节列和位字段列保持同步。
我已经解决了将它们一起滚动的问题。我将两个列表视图放在一个滚动面板中以达到我想要的效果。
我需要帮助的任务是计算分配每个左侧(字节)块的高度,以便字节块之间的转换与适当的位(第一个红色箭头)对齐,从而使总长度正确(第二个红色箭头)。(注意:我随机选择了数字,但目的是右侧列显示左侧列的字节中的位 - 相同的数据以不同的方式显示该数据。这就是我希望列对齐的原因。 )
它不是一个简单的数学计算的原因是块之间的边界占用空间,因此具有许多小位字段的部分将占用更多的垂直空间,而不是在较少字段中合并所有位的部分。我能够用复杂的代码来大致对齐它并计算它scale*num_bits + offset*num_transitions
,但没有值scale
和offset
(由反复试验确定)使它在所有情况下都对齐,并且对位字段框数据模板的任何调整都会需要找到新的scale
和offset
常数。
这是窗口的实际数据绑定代码。 {Binding Height}
是字节框的计算高度。
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Hidden">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="64"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView Grid.Column="0" ItemsSource="{Binding SerialDataBytes}">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="8" Height="{Binding Height}" Width="52" Margin="1,1,1,1">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Value}" />
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<local:BitDescriptionRow DataContext="{Binding SerialDataFields}" Grid.Column="1">
</local:BitDescriptionRow>
</Grid>
</ScrollViewer>
这是右侧列中用户控件的代码。{Binding Bits}
并{Binding BorderThickness}
在每八位之后生成带有粗体分隔符的 1 和 0 的垂直列表。 {Binding Height}
根据位数设置用户控件内容的高度。
<ListView ItemsSource="{Binding}">
<ListView.ItemTemplate >
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="8" Padding="4,4,4,4" Margin="1,1,1,1">
<StackPanel Orientation="Horizontal" Height="{Binding Height}">
<ListView VerticalAlignment="Center" VerticalContentAlignment="Center" BorderThickness="0" ItemsSource="{Binding Bits}">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderThickness="{Binding BorderThickness}" BorderBrush="Black">
<TextBlock Height="16" Text="{Binding Value}" />
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding FieldValue}" Margin="4,4,4,4" />
<TextBlock Width="180" Height="auto" TextWrapping="Wrap" Text="{Binding Description}" />
</StackPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
理想情况下,我认为如果字节框以某种方式动态(布局时间)同步,则最好是在示例模型中红色箭头所在的位置。如果这需要两步布局(闪烁)也没关系。在真实(非模拟)版本中,我使用 MVVM 和数据绑定。字节块的高度是一个数据绑定属性,所以我设想通过数据绑定进入视图模型的位域的布局高度/布局位置。
我出现的示例都涉及直接迭代 UIElements,我愿意接受这是更好的方法。但是如果我走那条路,我怎么知道哪个 UIElement 与哪个视图模型一起使用,因为它是通过数据绑定列表而不是静态布局动态的?
对预期评论的回答:
- 为什么不将字节块设为固定大小?
- 这是我的第一个想法,但我更喜欢这种布局。在此应用程序中,位字段包含重要项目,而字节块只是提供信息。如果字节块具有固定的高度,则 1 位字段将被压缩,更长的位字段将使用比必要更多的空间。
- 为什么不使用 DataGrid?
- 当左右列中的矩形在不同的行上结束时会很困难。可以想象像 2D 游戏那样将网格和边界视为一个图块集,并
|
-
L
根据需要生成等。除了非常复杂的这类作品(我试过了),但是当你点击描述标签时,它会抛出一个猴子扳手:多行文本应该跨越多个数据网格行。我无法理解合并单元格功能如何与数据绑定一起使用。如果您正在平铺边框元素 (|
-
L
) 并与数据网格作斗争,那么此时最好使用画布。
- 当左右列中的矩形在不同的行上结束时会很困难。可以想象像 2D 游戏那样将网格和边界视为一个图块集,并
- 为什么不使用网格?
- 我找不到将 Grid 与数据绑定元素一起使用的好例子,无论如何,对 DataGrid 的一些反对意见也适用于 Grid。
- 为什么不使用 Canvas 或以图形方式绘制?
- 我希望能够使用具有流和边距的常规 WPF 元素(ListView、Border 等),而不是手动绘制线条,无论哪种方式,您仍然需要计算有效偏移量。
解决方案
推荐阅读
- c# - 如何使用具有不同配置的 msbuild 构建项目,但在 Debug/Release 中构建依赖项?
- api - Instagram Graph API 未返回所有评论
- apache-camel - Camel FTP - 移动查询参数与 to() 方法
- mysql - 实体框架核心 - PersistKeysToDbContext mysql 问题
- flutter - “Runner”包含不在权利文件中的权利
- python - 获取所有 JIRA 项目里程碑的列表
- excel - 许多用户试图通过 ODBC (Microsfot Excel) 刷新链接到 BigQuery 的数据
- amazon-web-services - 如何为 Elastic beanstalk Cloudformation 模板提供 ECR 读取权限?
- linux - 电子无法运行 linux 应用程序并且找不到 background.js,但 windows 应用程序正在运行
- coinbase-api - API 中的 request_money 失败:coinbase.wallet.error.InvalidRequestError:APIError(id=invalid_request):缺少参数:`type`