【发布时间】:2013-02-27 03:00:06
【问题描述】:
我正在对类似工具栏的控件进行一些布局,并且在空间不足时需要隐藏按钮的文本。我已经在 Windows 窗体中成功完成了这项工作,现在我已将此逻辑移植到 WPF。但是这里有一个很大的问题:为了让我的算法正常工作,我需要知道容器控件的所需宽度(知道如果所有内容都可见则需要什么大小)和控件的实际宽度(知道如何确实很宽,以及是否有足够的空间容纳所需的宽度)。第一个是可用的,尽管有时有点倒退。 (如果可用空间多于所需空间,则 DesiredSize 会增加以将其全部填满,尽管较少也可以。)后一个完全不可用!
我已经尝试过 ActualWidth,但如果 Grid 比窗口宽,ActualWidth 就会超出实际可见的范围。所以这一定是错的。然后我尝试了 RenderSize,但它是一样的。在我的 Measure 调用之后使用 Arrange 会导致更多的怪异。
我需要知道控件的实际宽度,而不是它认为自己的宽度。如何确定该尺寸?
更新:好的,这里有一些代码。这个问题已经很长了,仍然不完整。这是来自 Window 的代码隐藏。
private void ToolGrid_LayoutUpdated(object sender, EventArgs e)
{
AutoCollapseItems();
}
private void AutoCollapseItems()
{
if (collapsingItems) return;
if (ToolGrid.ActualWidth < 10) return; // Something is wrong
try
{
collapsingItems = true;
// Collapse toolbar items in their specified priority to save space until all items
// fit in the toolbar. When collapsing, the item's display style is reduced from
// image and text to image-only. This is only applied to items with a specified
// collapse priority.
Dictionary<ICollapsableToolbarItem, int> collapsePriorities = new Dictionary<ICollapsableToolbarItem, int>();
// Restore the display style of all items that have a collpase priority.
var items = new List<ICollapsableToolbarItem>();
EnumCollapsableItems(ToolGrid, items);
foreach (var item in items)
{
if (item.CollapsePriority > 0)
{
item.ContentVisibility = Visibility.Visible;
collapsePriorities[item] = item.CollapsePriority;
}
}
// Group all items by their descending collapse priority and set their display style
// to image-only as long as all items don't fit in the toolbar.
var itemGroups = from kvp in collapsePriorities
where kvp.Value > 0
group kvp by kvp.Value into g
orderby g.Key descending
select g;
foreach (var grp in itemGroups)
{
//ToolGrid.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
//ToolGrid.Arrange(new Rect(ToolGrid.DesiredSize));
//ToolGrid.UpdateLayout();
System.Diagnostics.Debug.WriteLine("Desired=" + ToolGrid.DesiredSize.Width + ", Actual=" + ToolGrid.ActualWidth);
if (ToolGrid.DesiredSize.Width <= ToolGrid.ActualWidth) break;
foreach (var kvp in grp)
{
kvp.Key.ContentVisibility = Visibility.Collapsed;
}
}
//ToolGrid.UpdateLayout();
}
finally
{
collapsingItems = false;
}
}
更多代码:这是 Window XAML 的一部分:
<Window>
<DockPanel>
<Grid Name="ToolGrid" DockPanel.Dock="Top" LayoutUpdated="ToolGrid_LayoutUpdated">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
...
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>
【问题讨论】:
-
这是在安排/测量期间使用的吗?还是你通过绑定来做这个?
-
在代码隐藏中的 LayoutUpdated 事件上调用(但不是递归)。我还发现所需的宽度总是小于实际宽度。如果没有足够的空间,则 Desired 是可见的大小,Actual 是所需的。如果有足够的空间,则 Desired 是所需的大小,Actual 是可见的。所以这两个属性的含义转了转,我不知道哪个是哪个。没用。
-
一些代码会有所帮助,你是继承
UserControl还是Control? -
代码很多,几百行。我会避免把他们都撕到这个有限的阶段。只是普通的 Grid 容器,没有什么特别的项目。我目前正在窗口代码隐藏上进行此布局。当它更稳定时,我可能会将它放在单独的控件中。