Выберите родительский ListBoxItem при взаимодействии с CheckBox

Хотя простой вопрос. У меня есть приложение WPF (.NET 4.0). Существует список, который содержит ряд пользовательских панелей. Каждая из этих пользовательских панелей содержит флажок.

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

Требование: если вы установите флажок, это должно считаться выбором строки.

Управление флажком:

<UserControl x:Class="CheckboxClickExample.CheckboxControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="189" d:DesignWidth="221">
    <Grid>
        <CheckBox Content="CheckBox" Height="16" HorizontalAlignment="Left" Margin="10,10,0,0" Name="checkBox1" VerticalAlignment="Top" />
    </Grid>
</UserControl>

Главное окно:

<Window x:Class="CheckboxClickExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:checkboxsample="clr-namespace:CheckboxClickExample"
        Title="MainWindow" Height="350" Width="525">
    <ListBox>        
        <checkboxsample:CheckboxControl/>
        <checkboxsample:CheckboxControl/>
        <checkboxsample:CheckboxControl/>
        <checkboxsample:CheckboxControl/>
    </ListBox>
</Window>

person Eric    schedule 07.12.2011    source источник


Ответы (1)


Вы можете справиться с этим в своем коде UserControl:

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        var parent = sender as DependencyObject;

        while (parent != null)
        {
            if (parent is Selector)
                break;

            parent = VisualTreeHelper.GetParent(parent);
        }

        if (parent != null)
            ((Selector) parent).SelectedItem = this;
    }

А затем используйте обработчик в вашем CheckBox:

<CheckBox Content="CheckBox"
          Height="16"
          Click="ButtonBase_OnClick"
          HorizontalAlignment="Left"
          Margin="10,10,0,0"
          VerticalAlignment="Top" />

Изменить

Если вы не хотите использовать код, лучшее, что вы можете сделать, это упаковать существующее решение как прикрепленное поведение. Преимущество этого заключается в том, что вам нужно написать код только один раз и что свойство можно установить для любой кнопки, даже если она не является частью UserControl.

Например:

public static class ButtonClickHelper
{
    public static void SetEnableSelectionOnClick(ButtonBase button, bool value)
    {
        button.SetValue(EnableSelectionOnClickProperty, value);
    }

    public static bool GetEnableSelectionOnClick(ButtonBase button)
    {
        return (bool) button.GetValue(EnableSelectionOnClickProperty);
    }

    public static readonly DependencyProperty EnableSelectionOnClickProperty =
        DependencyProperty.RegisterAttached("EnableSelectionOnClick", typeof (bool), typeof (ButtonClickHelper),
                                            new FrameworkPropertyMetadata(OnEnableSelectionOnClickPropertyChanged));

    private static void OnEnableSelectionOnClickPropertyChanged(DependencyObject d,
                                                                DependencyPropertyChangedEventArgs e)
    {
        if (!(d is ButtonBase))
            return;

        var button = (ButtonBase) d;
        if ((bool) e.NewValue)
        {
            button.Click += OnButtonClick;
        }
        else
        {
            button.Click -= OnButtonClick;
        }
    }

    private static void OnButtonClick(object sender, RoutedEventArgs e)
    {
        var parent = sender as DependencyObject;
        var ancestors = new List<DependencyObject>();

        while (parent != null)
        {
            if (parent is Selector)
                break;

            parent = VisualTreeHelper.GetParent(parent);
            ancestors.Add(parent);
        }

        if (parent != null)
        {
            var selector = (Selector) parent;
            var itemToSelect = ancestors.Where(i => selector.Items.Contains(i)).FirstOrDefault();

            if (itemToSelect != null)
                ((Selector) parent).SelectedItem = itemToSelect;
        }
    }
}

Затем вы можете использовать это в своем XAML, просто установив свойство зависимости EnableSelectionOnClick:

<CheckBox Content="CheckBox"
          Height="16"
          l:ButtonClickHelper.EnableSelectionOnClick="True"
          HorizontalAlignment="Left"
          Margin="10,10,0,0"
          VerticalAlignment="Top" />

Надеюсь это поможет!

person FunnyItWorkedLastTime    schedule 07.12.2011