3

それで、カスタムデータテンプレートを備えたComboBoxがあるとしましょう。データテンプレートの項目の1つは、ボタンです。

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

これに伴う問題は、ボタンがクリックを食いつぶし、ボタンが選択されている場合、アイテムが選択されないことです。これは、プルダウンが消えず、アイテムが選択されていないことを意味します。

なぜこれが起こっているのかわかります。

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

注:Silverlightで問題が発生していますが、WPFでもまったく同じ動作が見られると思います。

4

4 に答える 4

8

OK、わかりました。これは完全なハックですが、それでもコマンドをボタンにバインドして、アイテムを選択するためのコンボボックスの動作を継続できます。

<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のハック拡張として維持することにしました。

于 2009-05-20T18:22:23.947 に答える
1

最善の策は、ボタンのコマンドでSelectedItemを設定することです。

于 2009-05-19T23:01:03.717 に答える
1

MVVMコンテキストの別の可能性を見つけました。の派生クラスを使用しましComboBoxた。アイテムがaddenである場合は、イベントButtonBaseにアタッチしてを閉じます。ClickComboBox

これは私のプロジェクトでは機能しますが、アイテム自体がボタンであるため、子要素としてボタンが含まれているだけでは機能しません。

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; };
    }
}
于 2012-07-02T11:26:25.100 に答える
0

あなたがやりたいことをする方法があるかどうかはわかりません。たとえば、をに入れた場合ButtonListBox同じ動作が発生します。クリックしButtonても、の項目はListBox選択されません。実際、これは、ItemsControl選択をサポートするのすべてのコントロールに当てはまります。

イベントで何かを実行し、Click処理されていないものとしてマークして、ビジュアルツリーを継続することができる場合がありますが、それでも、それが機能するかどうかはわかりません。

于 2009-05-19T16:12:00.713 に答える