2009-05-19 4 views
3

したがって、カスタムデータテンプレートを持つComboBoxがあるとします。ボタンを含むItemTemplateを持つComboBox

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

これに伴う問題は、ボタンがクリックを食べることで、ボタンが選択された場合に項目が選択されません:データテンプレート内の項目の一つはボタンです。これは、プルダウンが消えず、項目が選択されていないことを意味します。

私はこれがなぜ起こっているのですか?

回避策はありますか?おそらく、ボタンのクリックを処理する方法(私はコマンドにバインドしています)とコンボボックスもクリックを処理できるようにチェーンを続けるよう指示しますか?

注:私はSilverlightで私の問題を見ていますが、私はWPFで全く同じ動作が見られると推測しています。

答えて

1

おそらくボタンのコマンドでSelectedItemを設定するのがよいでしょう。

+0

ええ、私はそれを考えましたが、それを行うことは、コンボボックスが作成するプルダウンを却下しません。 –

+0

ComboBoxにはIsOpen(または非常に似たような)プロパティもありますが、Falseに設定することができます。また、ボタンにFocusable = "False"を設定して、それが自動的に起こるようにすることもできます。 –

+0

ええ、それは2つの組み合わせで終わった。私の答えは完全な解決策を見てください。しかし、私はあなたにクレジットポイントを与えたいので、あなたの答えを正しいものとしてマークしています。 –

0

あなたがしたいことをする方法があるかどうかわかりません。たとえば、ButtonListBoxに入れた場合、同じ動作が発生します。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のプロパティにバインドできますが、私はViewModelをきれいに保つために、この動作をXAMLのハック拡張として保持することに決めました。

1

私はMVVMコンテキストの別の可能性を発見しました。私はComboBoxの派生クラスを使用しました。項目がButtonBaseから派生する項目であれば、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; }; 
    } 
} 
関連する問題