我正在使用一个组合框,它从How can I make a WPF combo box have the width of its widest element in XAML?中附加的行为答案(目前是46个向上投票)中描述的最宽元素中获取宽度
public static void SetWidthFromItems(this ComboBox comboBox)
{
double comboBoxWidth = 19;// comboBox.DesiredSize.Width;
// Create the peer and provider to expand the comboBox in code behind.
ComboBoxAutomationPeer peer = new ComboBoxAutomationPeer(comboBox);
IExpandCollapseProvider provider = (IExpandCollapseProvider)peer.GetPattern(PatternInterface.ExpandCollapse);
EventHandler eventHandler = null;
eventHandler = new EventHandler(delegate
{
if (comboBox.IsDropDownOpen &&
comboBox.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
double width = 0;
foreach (var item in comboBox.Items)
{
var container = comboBox.ItemContainerGenerator.ContainerFromItem(item);
if (container is ComboBoxItem)
{
var comboBoxItem = (ComboBoxItem) container;
comboBoxItem.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
if (comboBoxItem.DesiredSize.Width > width)
{
width = comboBoxItem.DesiredSize.Width;
}
}
else
{
/* FIXME: coming here means that for some reason ComboBoxItems */
/* are not generated even if comboBox.ItemContainerGenerator.Status seems to be OK */
return;
}
}
comboBox.Width = comboBoxWidth + width;
// Remove the event handler.
comboBox.ItemContainerGenerator.StatusChanged -= eventHandler;
comboBox.DropDownOpened -= eventHandler;
provider.Collapse();
}
});
comboBox.ItemContainerGenerator.StatusChanged += eventHandler;
comboBox.DropDownOpened += eventHandler;
// Expand the comboBox to generate all its ComboBoxItem's.
provider.Expand();
}但是,当在win10中动态缩放文本大小时,该解决方案不起作用。问题是,即使条件是
comboBox.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated为真,则调用
comboBox.ItemContainerGenerator.ContainerFromItem(item); 从看似ok的项返回null。
所以我的问题是:我应该如何修改代码,以确保宽度计算正确?我问这个是因为我没有win10,不能复制和玩耍。我得请一个同事来测试一下。
我试着删除行
comboBox.ItemContainerGenerator.StatusChanged -= eventHandler;这导致在用鼠标单击窄的组合框时测量到正确的宽度。因此,一种解决方案是以某种方式强制在某个地方引发StatusChanged事件。
发布于 2017-08-17 21:00:55
我想出了一个解决方案,那就是远非完美的 up a worka round。测量只需要做一次,因为我不会在ComboBox准备好后添加项目。所以我记录了测量的ComboBoxes:
private static HashSet<string> _measuredWidthNamesSet = new HashSet<string>();
private static void OnComboBoxLoaded(object sender, RoutedEventArgs e)
{
ComboBox comboBox = sender as ComboBox;
if (!_measuredWidthNamesSet.Contains(comboBox.Name))
{
Action action = () => { comboBox.SetWidthFromItems(_measuredWidthNamesSet); };
comboBox.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle);
}
}如果comboBox.ItemContainerGenerator.ContainerFromItem(item)返回null,我们不会检查宽度,也不会将ComboBox名称添加到度量的ComboBoxes集合中:
public static void SetWidthFromItems(this ComboBox comboBox, HashSet<string> measuredWidthNamesSet)
{
double comboBoxWidth = 19;// comboBox.DesiredSize.Width;
// Create the peer and provider to expand the comboBox in code behind.
ComboBoxAutomationPeer peer = new ComboBoxAutomationPeer(comboBox);
IExpandCollapseProvider provider = (IExpandCollapseProvider)peer.GetPattern(PatternInterface.ExpandCollapse);
EventHandler eventHandler = null;
eventHandler = new EventHandler(delegate
{
if (comboBox.IsDropDownOpen &&
comboBox.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
bool isSuccess = true;
double width = 0;
foreach (var item in comboBox.Items)
{
var container = comboBox.ItemContainerGenerator.ContainerFromItem(item);
if (container is ComboBoxItem)
{
var comboBoxItem = (ComboBoxItem) container;
comboBoxItem.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
if (comboBoxItem.DesiredSize.Width > width)
{
width = comboBoxItem.DesiredSize.Width;
}
}
else
{
/* coming here means that for some reason ComboBoxItems are not generated even if
* comboBox.ItemContainerGenerator.Status seems to be OK */
isSuccess = false;
break;
}
}
if (isSuccess)
{
comboBox.Width = comboBoxWidth + width;
measuredWidthNamesSet.Add(comboBox.Name);
}
// Remove the event handler.
comboBox.ItemContainerGenerator.StatusChanged -= eventHandler;
comboBox.DropDownOpened -= eventHandler;
provider.Collapse();
}
});
comboBox.ItemContainerGenerator.StatusChanged += eventHandler;
comboBox.DropDownOpened += eventHandler;
// Expand the comboBox to generate all its ComboBoxItem's.
provider.Expand();
}https://stackoverflow.com/questions/45730146
复制相似问题