ComboBox с ItemTemplate, который включает в себя кнопку - PullRequest
3 голосов
/ 19 мая 2009

Итак, допустим, у меня есть ComboBox с пользовательским шаблоном данных. Одним из элементов в шаблоне данных является кнопка:

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

Проблема в том, что кнопка съедает щелчок, и элемент не выбирается, если кнопка выбрана. Это означает, что выпадающий список не исчезает, и ни один элемент не выбран.

Я понимаю, ПОЧЕМУ это происходит.

Есть ли способ обойти это? Возможно, способ обработать нажатие кнопки (я привязан к команде) и сказать ему продолжить цепочку, чтобы поле со списком могло также обрабатывать щелчок?

Примечание. Я вижу свою проблему в Silverlight, но предполагаю, что с WPF можно увидеть точно такое же поведение.

Ответы [ 4 ]

8 голосов
/ 20 мая 2009

ОК, я понял это. Это полный взлом, но он по-прежнему позволяет мне привязать мою команду к кнопке и по-прежнему использовать комбинированное окно для выбора элемента:

<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 голос
/ 02 июля 2012

Я нашел другую возможность для контекста 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; };
    }
}
1 голос
/ 20 мая 2009

Лучше всего было бы установить SelectedItem в команде кнопки.

0 голосов
/ 19 мая 2009

Я не знаю, есть ли способ сделать то, что вы хотите. Например, если вы поместите Button в ListBox, произойдет то же самое - нажатие Button не приведет к выбору его элемента в ListBox. Фактически, это относится к любому элементу управления в ItemsControl, который поддерживает выбор.

Возможно, вы сможете что-то сделать с событием Click и отметить его как не обработанное, чтобы оно продолжало отображаться в визуальном дереве, но даже тогда я не уверен, сработает ли это или нет.

...