2010-02-18 14 views
23

में लिस्टबॉक्स की स्क्रॉल स्थिति को कैसे नियंत्रित करें मुझे वर्टिकल स्क्रॉलिंग सक्षम के साथ एक बड़ा सूची बॉक्स मिला है, मेरे एमवीवीएम में नया और संपादित आईसीओएमंड्स है। मैं संग्रह के अंत में नया आइटम जोड़ रहा हूं लेकिन जब मैं अपने एमवीवीएम-एडकॉमंड को कॉल करता हूं तो मैं स्क्रॉलबार को अंत तक ऑटो स्थिति में भी चाहता हूं। मैं एप्लिकेशन के किसी अन्य भाग से एक आइटम संपादन योग्य (संपादनकॉमंड को किसी विशेष पंक्ति आइटम के साथ कॉल करके) भी बना रहा हूं ताकि मेरी ListBoxItem DataTrigger का उपयोग करके संपादन मोड में जा रहा हो, लेकिन मैं उस विशेष पंक्ति (ListBoxItem) को कैसे लाऊंगा स्क्रॉल स्थिति समायोजित करके देखें।एक एमवीवीएम डब्ल्यूपीएफ ऐप

यदि मैं इसे दृश्य पक्ष में कर रहा हूं तो मैं listBox.ScrollInToView (lstBoxItem) को कॉल कर सकता हूं। लेकिन एमवीवीएम परिप्रेक्ष्य से इस सामान्य स्क्रॉल समस्या को हल करने का सबसे अच्छा तरीका क्या है।

+0

ListBox चयन का उपयोग करके चेंज किया गया ईवेंट और ScrollIntoView विधि MVVM को तोड़ नहीं देती है। यह पूरी तरह से कार्यक्षमता देखते हैं और दृश्य द्वारा संभाला जाना चाहिए। दृश्य मॉडल को यह भी पता नहीं होना चाहिए कि ListBox मौजूद है या किसी ऑब्जेक्ट को देखने में कोई नियंत्रण है या नहीं। दृश्य मॉडल को केवल एक ही चीज करना चाहिए जिसे चयनित इटैम बदलना है, जो व्यू मॉडल में लिस्टबॉक्स की बाध्य संपत्ति होनी चाहिए। – Tim

उत्तर

27

मैं आमतौर पर ListBox पर सेट करता हूं। मेरी वी एम से

private void BringSelectionIntoView(object sender, SelectionChangedEventArgs e) 
    { 
     Selector selector = sender as Selector; 
     if (selector is ListBox) 
     { 
      (selector as ListBox).ScrollIntoView(selector.SelectedItem); 
     } 
    } 

मैं डिफ़ॉल्ट संग्रह दृश्य प्राप्त कर सकते हैं और MoveCurrent*() एक विधि का उपयोग सुनिश्चित करने के लिए है कि आइटम जा रहा है: तो फिर मैं इस तरह एक SelectionChanged हैंडलर जोड़ने और हमेशा दृश्य में चयनित आइटम लाने के लिए, कोड के साथ संपादित वर्तमान आइटम है।

CollectionViewSource.GetDefaultView(_myCollection).MoveCurrentTo(thisItem); 

नोट: देखें विज्ञापन इस संदर्भ में में फिर

using System.Windows.Controls; 
using System.Windows.Interactivity; 

namespace Jarloo.Sojurn.Behaviors 
{ 
    public sealed class ScrollIntoViewBehavior : Behavior<ListBox> 
    { 
     protected override void OnAttached() 
     { 
      base.OnAttached(); 
      AssociatedObject.SelectionChanged += ScrollIntoView; 
     } 

     protected override void OnDetaching() 
     { 
      AssociatedObject.SelectionChanged -= ScrollIntoView; 
      base.OnDetaching(); 
     } 

     private void ScrollIntoView(object o, SelectionChangedEventArgs e) 
     { 
      ListBox b = (ListBox) o; 
      if (b == null) 
       return; 
      if (b.SelectedItem == null) 
       return; 

      ListBoxItem item = (ListBoxItem) ((ListBox) o).ItemContainerGenerator.ContainerFromItem(((ListBox) o).SelectedItem); 
      if (item != null) item.BringIntoView(); 
     } 
    } 
} 

: ListBox.ScrollIntoView() उपयोग करने के लिए वर्चुअलाइजेशन को समायोजित करने के

+0

हां मेरी सूची दृश्य वर्चुअलाइज्ड है, उत्तर के लिए धन्यवाद डॉ। –

7

MVVM में इस का उपयोग कर संपादित आसानी से ऐसा तरह एक संलग्न व्यवहार के माध्यम से पूरा किया जा सकता शीर्ष:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 

और ऐसा करें:

<ListBox ItemsSource="{Binding MyData}" SelectedItem="{Binding MySelectedItem}"> 
     <i:Interaction.Behaviors> 
      <behaviors:ScrollIntoViewBehavior /> 
     </i:Interaction.Behaviors> 
</ListBox> 

अब जब चयनित इटैम व्यवहार बदलता है तो आपके लिए BringIntoView() कॉल करेगा।

1

ऊपर कोड आप के लिए काम नहीं करता है, तो यह एक कोशिश

public class ListBoxExtenders : DependencyObject 
{ 
    public static readonly DependencyProperty AutoScrollToCurrentItemProperty = DependencyProperty.RegisterAttached("AutoScrollToCurrentItem", typeof(bool), typeof(ListBoxExtenders), new UIPropertyMetadata(default(bool), OnAutoScrollToCurrentItemChanged)); 

    public static bool GetAutoScrollToCurrentItem(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(AutoScrollToSelectedItemProperty); 
    } 

    public static void SetAutoScrollToCurrentItem(DependencyObject obj, bool value) 
    { 
     obj.SetValue(AutoScrollToSelectedItemProperty, value); 
    } 

    public static void OnAutoScrollToCurrentItemChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) 
    { 
     var listBox = s as ListBox; 
     if (listBox != null) 
     { 
      var listBoxItems = listBox.Items; 
      if (listBoxItems != null) 
      { 
       var newValue = (bool)e.NewValue; 

       var autoScrollToCurrentItemWorker = new EventHandler((s1, e2) => OnAutoScrollToCurrentItem(listBox, listBox.Items.CurrentPosition)); 

       if (newValue) 
        listBoxItems.CurrentChanged += autoScrollToCurrentItemWorker; 
       else 
        listBoxItems.CurrentChanged -= autoScrollToCurrentItemWorker; 
      } 
     } 
    } 

    public static void OnAutoScrollToCurrentItem(ListBox listBox, int index) 
    { 
     if (listBox != null && listBox.Items != null && listBox.Items.Count > index && index >= 0) 
      listBox.ScrollIntoView(listBox.Items[index]); 
    } 

} 

प्रयोग XAML

<ListBox IsSynchronizedWithCurrentItem="True" extenders:ListBoxExtenders.AutoScrollToCurrentItem="True" ..../> 
3

में दे यह वह जगह है स्वीकार किए जाते हैं जवाब का जुड़ी संपत्ति प्रपत्र:

using System.Windows; 
using System.Windows.Controls; 

namespace CommonBehaviors 
{ 
    public static class ScrollCurrentItemIntoViewBehavior 
    { 
     public static readonly DependencyProperty AutoScrollToCurrentItemProperty = 
      DependencyProperty.RegisterAttached("AutoScrollToCurrentItem", 
       typeof(bool), typeof(ScrollCurrentItemIntoViewBehavior), 
       new UIPropertyMetadata(default(bool), OnAutoScrollToCurrentItemChanged)); 

     public static bool GetAutoScrollToCurrentItem(DependencyObject obj) 
     { 
      return (bool)obj.GetValue(AutoScrollToCurrentItemProperty); 
     } 

     public static void OnAutoScrollToCurrentItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
     { 
      var listBox = obj as ListBox; 
      if (listBox == null) return; 

      var newValue = (bool)e.NewValue; 
      if (newValue) 
       listBox.SelectionChanged += listBoxSelectionChanged; 
      else 
       listBox.SelectionChanged -= listBoxSelectionChanged; 
     } 

     static void listBoxSelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      var listBox = sender as ListBox; 
      if (listBox == null || listBox.SelectedItem == null || listBox.Items == null) return; 

      listBox.Items.MoveCurrentTo(listBox.SelectedItem); 
      listBox.ScrollIntoView(listBox.SelectedItem); 
     } 

     public static void SetAutoScrollToCurrentItem(DependencyObject obj, bool value) 
     { 
      obj.SetValue(AutoScrollToCurrentItemProperty, value); 
     } 
    } 
} 

उपयोग:

<ListBox ItemsSource="{Binding}" 
      IsSynchronizedWithCurrentItem="True" 
      behaviors:ScrollCurrentItemIntoViewBehavior.AutoScrollToCurrentItem="True">