2012-11-27 28 views
1

摘要:單擊列表框項目,DataTemplate中的文本框獲得焦點,但未選中列表框項目。WPF - ListBox ContentTemplate文本框MouseDown導致列表框項不被選中

我敢肯定這與事件冒泡有關,但我在這裏錯過了一些東西。

我有列表框。每個ListBoxItem的ContentTemplate都被分配給一個包含簡單文本框的DataTemplate。

此TextBox被設計爲顯示爲假的可編輯標籤。

問題:單擊文本框時,ListBox的selectedItem沒有被更新。該文本框正在吞噬mousedown事件,並且從未通知列表框將更新到新項目。

我覺得我在這裏失去了一些愚蠢的東西。有任何想法嗎?有沒有辦法強制事件冒泡到父級ListView?

我已經嘗試了一切,從製作文本框的背景Null到處理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; 
      } 
     } 
    } 

並用

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

優秀的解決方案。萬分感謝。像魅力一樣工作 – tronious

1

我改變事件處理程序是更常規支承使用ContainerFromElement和ItemContainerGenerator.IndexFromContainer方法中的任何選擇使用它。

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