我知道如何在代码中执行此操作,但这可以在XAML中完成吗?
Window1.xaml:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<ComboBox Name="ComboBox1" HorizontalAlignment="Left" VerticalAlignment="Top">
<ComboBoxItem>ComboBoxItem1</ComboBoxItem>
<ComboBoxItem>ComboBoxItem2</ComboBoxItem>
</ComboBox>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
Window1.xaml.cs:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
double width = 0;
foreach (ComboBoxItem item in ComboBox1.Items)
{
item.Measure(new Size(
double.PositiveInfinity, double.PositiveInfinity));
if (item.DesiredSize.Width > width)
width = item.DesiredSize.Width;
}
ComboBox1.Measure(new Size(
double.PositiveInfinity, double.PositiveInfinity));
ComboBox1.Width = ComboBox1.DesiredSize.Width + width;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Fre*_*lad 55
您无法在Xaml中直接执行此操作,但可以使用此附加行为.(宽度将在Designer中可见)
<ComboBox behaviors:ComboBoxWidthFromItemsBehavior.ComboBoxWidthFromItems="True">
<ComboBoxItem Content="Short"/>
<ComboBoxItem Content="Medium Long"/>
<ComboBoxItem Content="Min"/>
</ComboBox>
Run Code Online (Sandbox Code Playgroud)
附加行为ComboBoxWidthFromItemsProperty
public static class ComboBoxWidthFromItemsBehavior
{
public static readonly DependencyProperty ComboBoxWidthFromItemsProperty =
DependencyProperty.RegisterAttached
(
"ComboBoxWidthFromItems",
typeof(bool),
typeof(ComboBoxWidthFromItemsBehavior),
new UIPropertyMetadata(false, OnComboBoxWidthFromItemsPropertyChanged)
);
public static bool GetComboBoxWidthFromItems(DependencyObject obj)
{
return (bool)obj.GetValue(ComboBoxWidthFromItemsProperty);
}
public static void SetComboBoxWidthFromItems(DependencyObject obj, bool value)
{
obj.SetValue(ComboBoxWidthFromItemsProperty, value);
}
private static void OnComboBoxWidthFromItemsPropertyChanged(DependencyObject dpo,
DependencyPropertyChangedEventArgs e)
{
ComboBox comboBox = dpo as ComboBox;
if (comboBox != null)
{
if ((bool)e.NewValue == true)
{
comboBox.Loaded += OnComboBoxLoaded;
}
else
{
comboBox.Loaded -= OnComboBoxLoaded;
}
}
}
private static void OnComboBoxLoaded(object sender, RoutedEventArgs e)
{
ComboBox comboBox = sender as ComboBox;
Action action = () => { comboBox.SetWidthFromItems(); };
comboBox.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle);
}
}
Run Code Online (Sandbox Code Playgroud)
它的作用是调用ComboBox的一个名为SetWidthFromItems的扩展方法,它(无形地)展开并折叠自身,然后根据生成的ComboBoxItems计算宽度.(IExpandCollapseProvider需要对UIAutomationProvider.dll的引用)
然后是扩展方法SetWidthFromItems
public static class ComboBoxExtensionMethods
{
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)
{
ComboBoxItem comboBoxItem = comboBox.ItemContainerGenerator.ContainerFromItem(item) as ComboBoxItem;
comboBoxItem.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
if (comboBoxItem.DesiredSize.Width > width)
{
width = comboBoxItem.DesiredSize.Width;
}
}
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();
}
}
Run Code Online (Sandbox Code Playgroud)
这种扩展方法还提供了调用的能力
comboBox.SetWidthFromItems();
Run Code Online (Sandbox Code Playgroud)
在后面的代码中(例如在ComboBox.Loaded事件中)
mic*_*tan 30
如果没有以下任何一项,则不能在XAML中:
原因是我遇到的默认ComboBox ControlTemplates(Aero,Luna等)都将ItemsPresenter嵌套在Popup中.这意味着这些项目的布局将被推迟,直到它们实际可见.
一种简单的方法是修改默认的ControlTemplate,将最外层容器的MinWidth(它是Aero和Luna的Grid)绑定到PART_Popup的ActualWidth.当您单击下拉按钮时,您将能够让ComboBox自动同步它的宽度,而不是之前.
因此,除非您可以在布局系统中强制执行测量操作(可以通过添加第二个控件来执行),我认为不能这样做.
与往常一样,我对一个简短而优雅的解决方案持开放态度 - 但在这种情况下,代码隐藏或双控制/ ControlTemplate黑客攻击是我见过的唯一解决方案.
Alu*_*ord 10
是的,这个有点讨厌.
我过去所做的是在ControlTemplate中添加一个隐藏的列表框(其itemscontainerpanel设置为网格)同时显示每个项目,但其可见性设置为隐藏.
我很高兴听到任何更好的想法,不依赖于可怕的代码隐藏或你的观点必须理解它需要使用不同的控件来提供宽度来支持视觉效果(哎呀!).
基于上面的其他答案,这是我的版本:
<Grid HorizontalAlignment="Left">
<ItemsControl ItemsSource="{Binding EnumValues}" Height="0" Margin="15,0"/>
<ComboBox ItemsSource="{Binding EnumValues}" />
</Grid>
Run Code Online (Sandbox Code Playgroud)
HorizontalAlignment ="Left"使用包含控件的整个宽度来停止控件.高度="0"隐藏项目控件.
Margin ="15,0"允许在组合框项目周围添加额外的铬(我不害怕Chrome不可知).
归档时间: |
|
查看次数: |
49366 次 |
最近记录: |