2011-12-07 67 views
1

雖然很簡單的問題。我有一個WPF應用程序(.NET 4.0)。有一個包含許多用戶面板的列表框。每個這些用戶面板都包含一個複選框。在CheckBox交互時選擇父級ListBoxItem

運行時,您可以單擊除複選框本身之外的用戶面板的任何部分,並且列表框將選擇該行(在此簡單情況下,通過更改背景進行視覺指示)。如果您選中該框,則該行未被選中。

要求: 如果選中該複選框,則應該算作選擇行。

複選框控制:

<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> 

回答

2

你可以在後面的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; 
    } 

然後使用handler在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; 
     } 
    } 
} 

然後你就可以只設置EnableSelectionOnClick依賴屬性在XAML中使用此:

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

希望這有助於!