2009-05-19 59 views
3

因此,可以说我有一个带有自定义数据模板的组合框。在一个数据模板的项目是一个按钮:带有ItemTemplate的组合框,其中包含一个按钮

<ComboBox Width="150" ItemsSource="{Binding MyItems}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <Button Content="ClickMe" /> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

这样做的问题是,按钮吃的点击,如果选择了按钮不会被选择的项目。这意味着下拉不会消失,并且不会选择任何项目。

我明白这是为什么发生。

有没有办法解决它?可能是一种处理按钮点击的方式(我绑定到一个命令),并告诉它继续链,所以组合框也可以处理点击?

注意:我在Silverlight中看到我的问题,但我猜测WPF可以看到完全相同的行为。

回答

1

你最好的选择可能是在按钮的命令中设置SelectedItem。

+0

是的,我认为,但这样做并不能解除组合框创建的下拉菜单。 – 2009-05-20 12:20:55

0

我不知道是否有办法做你想做的。例如,如果您要将Button置于ListBox中,则会发生相同的行为 - 单击Button不会导致其在ListBox中的项目被选中。实际上,支持选择的ItemsControl中的任何控件都是这种情况。

你可能会对Click事件做些什么,并将其标记为未处理,以便继续显示可视化树,但即使如此,我也不确定这是否可行。

8

好的,我明白了。这是一个总的黑客,但它仍然让我我的命令绑定到该按钮,并不断有组合框行为选择项目:

<ComboBox x:Name="MyCombo" Width="150" ItemsSource="{Binding MyItems}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <Button Content="ClickMe" Click="Button_Click" /> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

而且在后面的代码:

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    MyCombo.SelectedItem = (sender as Button).DataContext; 
    MyCombo.IsDropDownOpen = false; 
} 

如果我真的想要,我可以将SelectedItem和IsDropDownOpen绑定到ViewModel中的属性,但我决定不要将此行为作为XAML的黑客扩展,以保持ViewModel清洁。

1

我发现MVVM上下文的另一种可能性。我使用派生类ComboBox,如果一个项目是来自ButtonBase的adden,我附加到Click事件以关闭ComboBox

这适用于我的项目 - 但只是,因为项目本身是按钮,如果它们只包含按钮作为子元素,它将不起作用。

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; }; 
    } 
} 
相关问题