2015-06-08 16 views
7

Mam problem z ListBoxItem s. Próbuję ustawić wszystkie elementy sterujące w ListBoxItem również je zaznacz, więc kliknięcie na TextBox, Label itp. Wybierze ListBoxItem. Do tej pory dość proste.WPF ListBoxItem ControlTemplate łamie niektóre MouseDown/Selection

Zmieniam również szablon ListBoxItem, aby zmienić wizualizację zaznaczenia z podświetlenia tła po prostu rysowanie obramowania. Również całkiem proste.

Połączenie tych dwóch, jednak wydaje się powodować pewne naprawdę irytujące problemy z MouseDown i PreviewMouseDown, szczególnie w moim przypadku dotyczące Label s w Grid, w których jeden tworzy „void” zajęte przez Grid przestrzeni.

Korzystanie snoop, widzę zdarzenie PreviewMouseDown zatrzymując się na ScrollViewer wewnątrz ListBox, a nie dzieje się aż do ListBoxItem.

click no worky

XAML:

<Window x:Class="ListBoxClickThroughTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" 
     Width="525" 
     Height="350"> 
    <Grid> 
     <ListBox ItemsSource="{Binding Items}" 
       SelectionMode="Single"> 

      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <Grid> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="Auto" /> 
          <ColumnDefinition Width="*" /> 
         </Grid.ColumnDefinitions> 
         <Grid.RowDefinitions> 
          <RowDefinition /> 
          <RowDefinition /> 
         </Grid.RowDefinitions> 

         <Label Name="VerySuperLongLabel" 
           Grid.Row="0" 
           Grid.Column="0" 
           HorizontalAlignment="Left" 
           Content="VerySuperLongLabel" 
           Padding="0" /> 

         <TextBox Name="Textbox1" 
           Grid.Row="0" 
           Grid.Column="1" 
           HorizontalAlignment="Stretch" 
           HorizontalContentAlignment="Right" 
           Text="Textbox1 Text" /> 


         <Label Name="ShortLabel" 
           Grid.Row="1" 
           Grid.Column="0" 
           HorizontalAlignment="Left" 
           Content="ShortLabel" 
           Padding="0" /> 
         <TextBox Name="Textbox2" 
           Grid.Row="1" 
           Grid.Column="1" 
           HorizontalAlignment="Stretch" 
           HorizontalContentAlignment="Right" 
           Text="Textbox2 Text" /> 
        </Grid> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 

      <ListBox.ItemContainerStyle> 
       <Style TargetType="{x:Type ListBoxItem}"> 
        <EventSetter Event="PreviewMouseDown" 
           Handler="ListBoxItem_PreviewMouseDown" /> 
        <EventSetter Event="MouseDown" 
           Handler="ListBoxItem_PreviewMouseDown" /> 
        <Setter Property="HorizontalContentAlignment" Value="Stretch" /> 
        <Setter Property="Template"> 
         <Setter.Value> 
          <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
           <Border x:Name="Bd" 
             BorderThickness="1"> 
            <ContentPresenter /> 
           </Border> 
           <ControlTemplate.Triggers> 
            <Trigger Property="IsSelected" Value="true"> 
             <Setter TargetName="Bd" Property="BorderBrush" Value="Gray" /> 
            </Trigger> 
           </ControlTemplate.Triggers> 
          </ControlTemplate> 
         </Setter.Value> 
        </Setter> 
       </Style> 
      </ListBox.ItemContainerStyle> 
     </ListBox> 

    </Grid> 
</Window> 

Code-tył:

using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 

namespace ListBoxClickThroughTest 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      Items = new List<string>() { "1", "2" }; 
      InitializeComponent(); 
      DataContext = this; 
     } 

     public List<string> Items { get; set; } 

     private void ListBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
     { 
      var listBoxItem = (ListBoxItem)sender; 
      listBoxItem.IsSelected = true; 
     } 
    } 
} 

Jednak jeśli usunąć Template setter, wszystko jest dobrze. Czy w szablonie brakuje jakiejś magii? Próbowałem zmienić nazwę ramki na "Bd", ponieważ była to nazwa domyślnej granicy szablonu, ale bez powodzenia. Jakieś pomysły?

+0

Czy próbujesz uzyskać obramowanie rysowane po kliknięciu w białą spację na prawo od drugiego elementu listy? –

+0

@aaron, Próbuję wybrać 'ListBoxItem' klikając w nim _anywhere_ i pokazując zaznaczenie za pomocą ramki (jak górny wybrany element na zrzucie ekranu). Kod działa wszędzie z wyjątkiem pustki po prawej stronie "ShortLabel". –

+0

Nie wiedziałeś, że możesz używać Snoopa do oglądania wydarzeń! – Contango

Odpowiedz

5

Po zmianie poziomego wyrównania etykiet z "Left" na "Stretch" rozwiąże to problem i zachowa formatowanie wizualne.

Wydarzenia Mousedown działają tylko w obszarach, w których istnieją elementy. Mając etykiety w "lewym" wyrównaniu poziomym, tworzysz "pustkę", o której wspomniałeś, gdzie nie ma elementu na tym poziomie, który można kliknąć. Aby zobaczyć różnicę, spróbuj tymczasowo ustawić właściwość tła elementów etykiet, które dają problemy, a zobaczysz, że element nie rozszerza się do pola tekstowego.

+0

Genialny! To naprawia długotrwały problem, który miałem w moim projekcie. – Contango

+0

Takie proste. Dziękuję Ci! Pomyślałem, że 'ListBoxItem' otrzyma zdarzenie' MouseDown' w takiej sytuacji, w której jest pustka. Dzięki jeszcze raz! –

+0

Każdy pomysł, dlaczego 'ListBoxItem' nie otrzymuje zdarzenia? Czuję, że to dobre rozwiązanie, ale nie wyjaśnia, dlaczego to wydarzenie zdaje się ginąć w 'ScrollViewer'. –

Powiązane problemy