2012-10-06 25 views
7

MVVM kullanıyorum ve bir pencerede iki liste kutusu görüntülüyorum. Her iki listeden de eşzamanlı olarak farklı alanlara A ve B olarak adlandırıyorum. A ve B her ikisi de C'yi değiştiriyor. Bu çalışmayı yapmak için, iki liste kutusundan bir defada tek bir öğe istiyorum. B isSelected olduğunda C'yi geçersiz kılmaz. Bunu nasıl kısıtlayabilirim?Tek bir öğede seçili olan birden çok WPF ListBox'ları

Teşekkürler!

+1

Başka bir ListBox'ta seçim yapıldığında seçimin bir ListBox'ta temizlenmesini istiyorsunuz? Sorunu anlamak zor. – Simon

+0

Temel olarak, görünüm modelimde bir IsFocused/IsSelected Listbox özelliği gibi bir şeyi nasıl bağlayabileceğimi bilmek istiyorum. – user1722960

+2

ListBox'un SelectedIndex'ini görünüm modelinizdeki bir özelliğe bağlayabilirsiniz. Örneğin, ListBoxA'nın SelectedIndexA'sı ayarlandığında, ListBoxB'nin SelectedIndexB'sini - ListboxB'nin seçimini (seçimini) ve tersini de - ayarlamak için -1'e ayarlayabilirsiniz. Bu senin niyetin mi? – Simon

cevap

8

Bunu yapmanın birkaç yolunu düşünebilirim.

Tek bir şekilde ViewModel özelliklerini değiştirmek için 2 ListBox'unuzun ListBox.SelectedIndex'unu bağlayabilirsiniz.

senin görünümünde Örneğin

:

<ListBox SelectedIndex="{Binding SelectedIndexA}"> 
    <ListBoxItem Content="Item 1"/> 
    <ListBoxItem Content="Item 2"/> 
</ListBox> 
<ListBox SelectedIndex="{Binding SelectedIndexB}"> 
    <ListBoxItem Content="Item 1"/> 
    <ListBoxItem Content="Item 2"/> 
</ListBox> 

Ve ViewModel:

public int SelectedIndexA 
{ 
    get { return _selectedIndexA; } 
    set 
    { 
     _selectedIndexA = value; 
     _selectedIndexB = -1; 
     OnPropertyChanged("SelectedIndexB"); 
    } 
} 

public int SelectedIndexB 
{ 
    get { return _selectedIndexB; } 
    set 
    { 
     _selectedIndexB = value; 
     _selectedIndexA = -1; 
     OnPropertyChanged("SelectedIndexA"); 
    } 
} 

'GrupAdı' gibi iliştirilmiş bir özellik ile olacağını başka bir yolu da yapabileceğiniz grup Seçiciler (ListBox devralır gelen Selector) Grubun içinde yalnızca bir tane Selector olduğundan emin olmak için seçilen bir öğe herhangi bir zamanda seçilebilir.

public static class SingleSelectionGroup 
{ 
    public static readonly DependencyProperty GroupNameProperty = 
     DependencyProperty.RegisterAttached("GroupName", typeof(string), typeof(SingleSelectionGroup), 
              new UIPropertyMetadata(OnGroupNameChanged)); 

    public static string GetGroupname(Selector selector) 
    { 
     return (string) selector.GetValue(GroupNameProperty); 
    } 

    public static void SetGroupName(Selector selector, string value) 
    { 
     selector.SetValue(GroupNameProperty, value); 
    } 

    private static void OnGroupNameChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
    { 
     var selector = (Selector) dependencyObject; 

     if (e.OldValue != null) 
      selector.SelectionChanged -= SelectorOnSelectionChanged; 
     if (e.NewValue != null) 
      selector.SelectionChanged += SelectorOnSelectionChanged; 
    } 

    private static void SelectorOnSelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     if (e.AddedItems.Count == 0) 
      return; 

     var selector = (Selector) sender; 
     var groupName = (string) selector.GetValue(GroupNameProperty); 
     var groupSelectors = GetGroupSelectors(selector, groupName); 

     foreach (var groupSelector in groupSelectors.Where(gs => !gs.Equals(sender))) 
     { 
      groupSelector.SelectedIndex = -1; 
     } 
    } 

    private static IEnumerable<Selector> GetGroupSelectors(DependencyObject selector, string groupName) 
    { 
     var selectors = new Collection<Selector>(); 
     var parent = GetParent(selector); 
     GetGroupSelectors(parent, selectors, groupName); 
     return selectors; 
    } 

    private static DependencyObject GetParent(DependencyObject depObj) 
    { 
     var parent = VisualTreeHelper.GetParent(depObj); 
     return parent == null ? depObj : GetParent(parent); 
    } 

    private static void GetGroupSelectors(DependencyObject parent, Collection<Selector> selectors, string groupName) 
    { 
     var childrenCount = VisualTreeHelper.GetChildrenCount(parent); 
     for (int i = 0; i < childrenCount; i++) 
     { 
      var child = VisualTreeHelper.GetChild(parent, i); 
      var selector = child as Selector; 
      if (selector != null && (string) selector.GetValue(GroupNameProperty) == groupName) 
       selectors.Add(selector); 

      GetGroupSelectors(child, selectors, groupName); 
     } 
    } 
} 

Ve Görünüm: Örneğin:

:

<ListBox my:SingleSelectionGroup.GroupName="Group A"> 
    <ListBoxItem Content="Item 1 (Group A)"/> 
    <ListBoxItem Content="Item 2 (Group A)"/> 
</ListBox> 
<ListBox my:SingleSelectionGroup.GroupName="Group A"> 
    <ListBoxItem Content="Item 1 (Group A)"/> 
    <ListBoxItem Content="Item 2 (Group A)"/> 
</ListBox> 

<ListBox my:SingleSelectionGroup.GroupName="Group B"> 
    <ListBoxItem Content="Item 1 (Group B)"/> 
    <ListBoxItem Content="Item 2 (Group B)"/> 
</ListBox> 
<ListBox my:SingleSelectionGroup.GroupName="Group B"> 
    <ListBoxItem Content="Item 1 (Group B)"/> 
    <ListBoxItem Content="Item 2 (Group B)"/> 
</ListBox> 

bunu böyle hızlı bir çözümü kullanabilirsiniz vurgulanır önce iki kez bir öğeyi tıklamak için varsa

<Style TargetType="ListBoxItem"> 
    <Style.Triggers> 
     <EventTrigger RoutedEvent="GotKeyboardFocus"> 
      <BeginStoryboard> 
       <Storyboard> 
        <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(ListBoxItem.IsSelected)"> 
         <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True" /> 
        </BooleanAnimationUsingKeyFrames> 
       </Storyboard> 
      </BeginStoryboard> 
     </EventTrigger> 
    </Style.Triggers> 
</Style> 
+0

harika cevap! Aşağıdaki cevaba bir düzeltme yaptık. Hala küçük bir problemim var. Çözmeyi deneyebilirseniz, o zaman sizin için çok güzel olacaktır. Özgür olursanız, lütfen sorunuma bir bakın: http://stackoverflow.com/questions/22209877/movefocus-from-one-listbox-to-another – Vishal

6

ListBox/ListView öğelerini ItemsControl içinde kullandıysa ve aşağıdaki sorunu varsa yukarıdaki cevabı kullandıktan sonra:

  1. Eğer öğe seçildiğinde ListBox1 herhangi Öğe tıkladığınızda.
  2. Listbox2'deki herhangi bir öğeye tıkladığınızda, liste kutusunun1 seçili öğesi seçili değil, ancak listbox2 öğesinde hiçbir öğe seçilmez.
  3. Liste kutusu2'deki herhangi bir öğeye tekrar tıkladığınızda, öğe seçilir. Herkes yukarıdaki cevap kodu kullandıktan sonra aşağıdaki hatayı azalıyorsa,

    <Style TargetType="ListBoxItem"> 
        <Style.Triggers> 
         <Trigger Property="IsKeyboardFocusWithin" Value="True"> 
          <Setter Property="IsSelected" Value="True"></Setter> 
         </Trigger> 
        </Style.Triggers> 
    </Style> 
    

    Ayrıca:

    GroupName is already registered by Selector 
    

    Lütfen

Sadece ListBoxItem stiline xaml altına ekleyin Bağımlılık özelliği bildiriminde third parameter typeof(......) değerini olarak değiştirin. Sınıfınızın adı.

+0

Bu mükemmel bir takip. Teşekkür ederim! – usefulBee

+0

@usefulBee Rica ederim. – Vishal

+0

Bunu incelediğiniz için teşekkür ederiz. Ekli mülkiyete bugüne kadar ihtiyacım yoktu, bu yüzden vurgulanan seçili öğelerle sorunu tespit ettim. Hızlı bir düzeltme olarak, yukarıdaki değer yerine bir EventTrigger kullandım çünkü değer yanlış olduğunda normal tetikleyiciler sıfırlanır, öğe klavye odağını kaybettiğinde anlam seçimi silinir. Bu durum benim durumumda istenmeyen bir durumdu. – Simon

İlgili konular