wpf 带有 ItemTemplate 的 ComboBox,其中包含一个按钮
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/883626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ComboBox with ItemTemplate that includes a button
提问by Brian Genisio
So, lets say I have a ComboBox with a custom data template. One of the items in the data template is a button:
所以,假设我有一个带有自定义数据模板的 ComboBox。数据模板中的一项是按钮:
<ComboBox Width="150" ItemsSource="{Binding MyItems}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Button Content="ClickMe" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The problem with this is that the button eats the click, and the item does not get selected if the button is selected. This means that the pull-down does not go away, and no item is selected.
这样做的问题是按钮会吃掉点击,如果选择了按钮,则项目不会被选中。这意味着下拉不会消失,也不会选择任何项目。
I get WHY this is happening.
我明白为什么会这样。
Is there a way to work around it? Possibly a way to process the button click (I am binding to a command) and tell it to continue up the chain so the combo box can also process the click?
有没有办法解决它?可能是一种处理按钮点击的方法(我绑定到一个命令)并告诉它继续向上链,以便组合框也可以处理点击?
Note: I am seeing my problem in Silverlight, but I am guessing that the exact same behavior can be seen with WPF.
注意:我在 Silverlight 中看到了我的问题,但我猜测在 WPF 中可以看到完全相同的行为。
采纳答案by Bryan Anderson
Your best bet would probably be to set the SelectedItem in the button's command.
您最好的选择可能是在按钮的命令中设置 SelectedItem。
回答by Brian Genisio
OK, I got it figured out. It is a total hack, but it still lets me bind my command to the button and continue to have Combo-box behavior for selecting the item:
好的,我明白了。这是一个彻底的黑客,但它仍然让我将我的命令绑定到按钮并继续使用组合框行为来选择项目:
<ComboBox x:Name="MyCombo" Width="150" ItemsSource="{Binding MyItems}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Button Content="ClickMe" Click="Button_Click" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And in the code behind:
在后面的代码中:
private void Button_Click(object sender, RoutedEventArgs e)
{
MyCombo.SelectedItem = (sender as Button).DataContext;
MyCombo.IsDropDownOpen = false;
}
If I really wanted to, I could bind the SelectedItem and IsDropDownOpen to properties in my ViewModel but I decided against it to keep this behavior as a hack extension of the XAML, in an effort to keep my ViewModel clean.
如果我真的想要,我可以将 SelectedItem 和 IsDropDownOpen 绑定到我的 ViewModel 中的属性,但我决定反对它,将这种行为作为 XAML 的黑客扩展,以保持我的 ViewModel 干净。
回答by MatthiasG
I found another possibility for the MVVM context. I used an derived class for ComboBox
and if an item is adden which derives from ButtonBase
I attach to the Click
event to close the ComboBox
.
我发现了 MVVM 上下文的另一种可能性。我使用了派生类ComboBox
,如果添加了一个派生自的项目,ButtonBase
我将附加到Click
事件以关闭ComboBox
.
This works for my project - but just, because the items itself are buttons, it would not work if they just contain buttons as a child element.
这适用于我的项目 - 但只是因为项目本身是按钮,如果它们只包含按钮作为子元素,它将不起作用。
public class MyComboBox : ComboBox
{
public MyComboBox()
{
// use Loaded event to modify inital items.
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
if (Items != null)
{
foreach (var item in Items)
{
var button = item as ButtonBase;
if (button != null)
{
ModifyButtonItem(button);
}
}
}
}
protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
// Check added items. If an item is a button, modify the button.
if (e.NewItems != null)
{
foreach (var item in e.NewItems)
{
var button = item as ButtonBase;
if (button != null)
{
ModifyButtonItem(button);
}
}
}
}
private void ModifyButtonItem(ButtonBase button)
{
button.Click += (sender, args) => { IsDropDownOpen = false; };
}
}
回答by Andy
I don't know if there is a way to do what you want. If you were to put a Button
in a ListBox
, for example, the same behavior occurs - clicking the Button
does not cause its item in the ListBox
to be selected. In fact, this is the case for any control in an ItemsControl
that supports selection.
我不知道是否有办法做你想做的事。例如,如果您将 aButton
放入 a ListBox
,则会发生相同的行为 - 单击Button
不会导致其在 中的项目ListBox
被选中。事实上,任何ItemsControl
支持选择的控件都是这种情况。
You might be able to do something with the Click
event and mark it as not handled so that it continues up the visual tree, but even then I'm not sure if that would work or not.
您也许可以对Click
事件做一些事情并将其标记为未处理,以便它在可视化树中继续向上,但即使如此,我也不确定这是否可行。