2012-11-27 4 views
1

요약 : 목록 상자 항목을 클릭하면 DataTemplate의 텍스트 상자에 포커스가 있지만 listBox 항목이 선택되지 않습니다.WPF - ListBox ContentTemplate textbox 목록 상자 항목을 선택하지 않게하는 MouseDown

이것은 이벤트 버블 링과 관련이 있지만 여기에는 뭔가 빠져 있습니다.

나는 ListBox를 가지고 있습니다. 각 ListBoxItem의 ContentTemplate은 간단한 텍스트 상자를 포함하는 DataTemplate에 할당됩니다.

이 TextBox는 편집 가능한 가짜 레이블로 표시되도록 설계되었습니다.

문제점 : 입력란을 클릭하면 ListBox의 selectedItem이 업데이트되지 않습니다. 텍스트 상자가 mousedown 이벤트를 삼키고 있으며 목록 상자에 새 항목을 업데이트하라는 메시지가 표시되지 않습니다.

내가 바보 같은 것을 놓치고있는 것처럼 느껴진다. 어떤 아이디어? 이벤트가 상위 ListView에 강제로 표시되도록하는 방법이 있습니까?

나는 텍스트 상자의 배경 널을 previewmousedown 이벤트를 처리하고 e.handled = false;로 설정하는 모든 것을 시도했다.

DataTemplate을 :

<DataTemplate x:Key="ItemTempl"> 
      <TextBox Height="20" Width="200" Name="tbox" Text="{Binding WordText}" HorizontalAlignment="Stretch"> 
       <TextBox.Style> 
        <Style TargetType="TextBox"> 
         <Setter Property="BorderThickness" Value="0"/> 
         <Setter Property="Background" Value="{x:Null}"/> 
         <Style.Triggers> 
          <DataTrigger Binding="{Binding Path=IsFocused, ElementName=tbox}" Value="True"> 
           <Setter Property="BorderThickness" Value="1"/> 
           <Setter Property="Background" Value="White"/>          
          </DataTrigger> 
         </Style.Triggers> 
        </Style> 
       </TextBox.Style> 
      </TextBox> 
</DataTemplate> 

목록보기 :

<ListView HorizontalAlignment="Stretch" ItemsSource="{Binding Something.Words}" Name="MainListView" SelectedItem="{Binding CurrentItem, Mode=TwoWay}" BorderThickness="0" ItemContainerStyle="{StaticResource ContainerStyle}"> 
</ListView> 
+1

ListView에 'ItemTempl'이 사용되지 않습니다. 또한 'ContainerStyle'이 무엇인지 설명하지 않았습니다. – Blachshma

답변

2
내가 이벤트 아래 미리보기 마우스를 처리하는 내 자신의 목록보기를 작성하여 ListView에이 특정 문제를 해결했고, 당신은 할 수 항목을 선택

이 상황에 적응 시키려면 첨부 된 속성에서이 작업을 수행하는 것이 가장 좋으므로 새 클래스를 만들 필요가 없습니다.

기본적으로 텍스트 상자 인 마우스의 원래 소스를 찾고 비주얼 트리 도우미를 사용하여 시각적 트리를 따라 앉아서 목록보기 항목까지 되돌아 가서 선택합니다.

public class MyListView : ListView 
    { 
     protected override void OnPreviewMouseDown(System.Windows.Input.MouseButtonEventArgs e) 
     { 
      DependencyObject listViewItem = (DependencyObject)e.OriginalSource; 
      while (listViewItem != null && !(listViewItem is ListViewItem)) 
       listViewItem = VisualTreeHelper.GetParent(listViewItem); 

      SelectedItem = ((ListViewItem)listViewItem).Content; 

      base.OnPreviewMouseDown(e); 
     } 
    } 

편집 : 여기에 연결된 속성 버전입니다.

public class ListViewExtras : DependencyObject 
    { 
     public static bool GetWillAlwaysSelect(DependencyObject obj) 
     { 
      return (bool)obj.GetValue(WillAlwaysSelectProperty); 
     } 

     public static void SetWillAlwaysSelect(DependencyObject obj, bool value) 
     { 
      obj.SetValue(WillAlwaysSelectProperty, value); 
     } 

     // Using a DependencyProperty as the backing store for WillAlwaysSelect. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty WillAlwaysSelectProperty = 
      DependencyProperty.RegisterAttached("WillAlwaysSelect", typeof(bool), typeof(ListViewExtras), new PropertyMetadata(false, new PropertyChangedCallback((s, e) => 
      { 
       ListView listView = s as ListView; 
       if (listView != null) 
       { 
        if ((bool)e.NewValue) listView.PreviewMouseDown += listView_PreviewMouseDown; 
        if (!(bool)e.NewValue && (bool)e.OldValue) listView.PreviewMouseDown -= listView_PreviewMouseDown; 
       } 
      }))); 

     static void listView_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) 
     { 
      ListView listView = sender as ListView; 
      if (listView != null) 
      { 
       DependencyObject listViewItem = (DependencyObject)e.OriginalSource; 
       while (listViewItem != null && !(listViewItem is ListViewItem)) 
        listViewItem = VisualTreeHelper.GetParent(listViewItem); 
       listView.SelectedItem = ((ListViewItem)listViewItem).Content; 
      } 
     } 
    } 

및 I는 ContainerFromElement ItemContainerGenerator.IndexFromContainer 및 방법을 사용하는 선택을 지원하는 일반적인로 이벤트 핸들러를 변경

<ListView HorizontalContentAlignment="Stretch" local:ListViewExtras.WillAlwaysSelect="True"> 
+0

우수한 해결책. 엄청 고마워. 매력처럼 작동했습니다. – tronious

1

함께 사용.

private static void OnPreviewListBoxMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     var listBox = sender as Selector; 
     if (listBox != null) 
     { 
      DependencyObject mouseItem = e.OriginalSource as DependencyObject; 
      if (mouseItem != null) 
      { 
       // Get the container based on the element 
       var container = listBox.ContainerFromElement(mouseItem); 
       if (container != null) 
       { 
        var index = listBox.ItemContainerGenerator.IndexFromContainer(container); 
        Debug.Assert(index >= 0); 
        listBox.SelectedIndex = index; 
       } 
      } 
     } 
    }