2011-01-25 14 views
17

में परिवर्तनबॉक्स सूची स्क्रॉल स्थिति को रीसेट करें, वर्तमान में मेरे पास एक सूची बॉक्स है जिसका आइटम्ससोर्स संग्रह मेरे व्यूमोडेल पर एक संपत्ति से जुड़ा हुआ है, टाइप करें INumerable। जब उस प्रीप्रॉर्टी का संदर्भ बदलता है, तो सूची बॉक्स अपडेट के रूप में अपडेट होता है, हालांकि मुझे इसमें कोई समस्या है यदि मेरे पास आइटम का एक बड़ा संग्रह है और ListBox के नीचे स्क्रॉल करें, और उसके बाद संदर्भ को किसी अन्य संग्रह में बदलें, कहें, 1 आइटम , Listbox दृश्य खाली है और कोई स्क्रॉलबार प्रदर्शित नहीं होता है। तब मुझे माउस व्हील के साथ सूची बॉक्स को स्क्रॉल करना होगा, जब तक कि 1 आइटम दृश्य में न आए।डब्ल्यूपीएफ - आइटम्ससोर्स

तो, मुझे लगता है कि मैं बाद में क्या कर रहा हूं, जब भी आइटम्स स्रोत संपत्ति बदलती है, तो सूची बॉक्स की स्क्रॉल स्थिति को रीसेट करने का एक तरीका है, ताकि कुछ हमेशा प्रदर्शित होता है चाहे संग्रह कितना बड़ा या छोटा हो। (जब ItemsSource बदलते मेरे लिए, ListBox नए संग्रह में अंतिम आइटम के लिए स्क्रॉल किया जाता है)

if (listBox.Items.Count > 0) { 
    listBox.ScrollIntoView(listBox.Items[0]); 
} 
+0

क्या मैं आपके प्रश्न को सही ढंग से समझता था या आप कुछ और ढूंढ रहे थे? –

+0

@Meleak धन्यवाद! वह दृष्टिकोण उपयोगी होगा। मैंने वास्तव में वर्चुअलाइजिंग टाइलपैनल को समस्या का पता लगाया है कि मेरा लिस्टबॉक्स उपयोग कर रहा है जिसे मैंने http://blogs.msdn.com/b/dancre/archive/2006/02/16/implementing-a-virtualizingpanel-part से लिया है -4--goods.aspx। समस्या को नीचे स्क्रॉल करके नमूना डाउनलोड पर दोहराया जा सकता है, और उसके बाद बाध्य संग्रह को एक आइटम के साथ बदल दिया जा सकता है। जब तक आप माउस व्हील के साथ स्क्रॉल नहीं करते हैं तब तक दृश्य खाली हो जाता है। – devdigital

+0

वर्चुअलाइजिंग टाइलपैनल के लिए http://social.msdn.microsoft.com/Forums/en/wpf/thread/05c5868b-7c91-4726-81fb-9af634c74d4a पर एक उत्तर मिला, लेकिन मैंने बाइनरीमिशन से वर्चुअलाइजिंग wrappanel पर स्विच किया है - http://www.binarymission.co.uk/binaryvirtwrappanelsl3.htm – devdigital

उत्तर

20

मैं आपकी समस्या को पुन: पेश करने में असमर्थ हूं:

+0

यह वास्तव में उपयोगी था :) –

1

इस प्रयास करें। वैसे भी, ListBox शीर्ष पर शीर्ष पर ItemsSource परिवर्तनों को स्क्रॉल करने के लिए आप कुछ कोड का उपयोग कर सकते हैं। सबसे पहले ItemsSourceProperty में बदलाव के लिए सुनने और उसके बाद शीर्ष करने के लिए स्क्रॉल ListBox एक बार अपने आइटम

तैयार की गई है अद्यतन

एक संलग्न व्यवहार इस बजाय कोड के पीछे से बचने के लिए करता है कि मेड।

एक सरल समाधान है: यह इस

<ListBox ... 
     behaviors:ScrollToTopBehavior.ScrollToTop="True"/> 

ScrollToTopBehavior

public static class ScrollToTopBehavior 
{ 
    public static readonly DependencyProperty ScrollToTopProperty = 
     DependencyProperty.RegisterAttached 
     (
      "ScrollToTop", 
      typeof(bool), 
      typeof(ScrollToTopBehavior), 
      new UIPropertyMetadata(false, OnScrollToTopPropertyChanged) 
     ); 
    public static bool GetScrollToTop(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(ScrollToTopProperty); 
    } 
    public static void SetScrollToTop(DependencyObject obj, bool value) 
    { 
     obj.SetValue(ScrollToTopProperty, value); 
    } 
    private static void OnScrollToTopPropertyChanged(DependencyObject dpo, 
                DependencyPropertyChangedEventArgs e) 
    { 
     ItemsControl itemsControl = dpo as ItemsControl; 
     if (itemsControl != null) 
     { 
      DependencyPropertyDescriptor dependencyPropertyDescriptor = 
        DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(ItemsControl)); 
      if (dependencyPropertyDescriptor != null) 
      { 
       if ((bool)e.NewValue == true) 
       { 
        dependencyPropertyDescriptor.AddValueChanged(itemsControl, ItemsSourceChanged); 
       } 
       else 
       { 
        dependencyPropertyDescriptor.RemoveValueChanged(itemsControl, ItemsSourceChanged); 
       } 
      } 
     } 
    } 
    static void ItemsSourceChanged(object sender, EventArgs e) 
    { 
     ItemsControl itemsControl = sender as ItemsControl; 
     EventHandler eventHandler = null; 
     eventHandler = new EventHandler(delegate 
     { 
      if (itemsControl.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) 
      { 
       ScrollViewer scrollViewer = GetVisualChild<ScrollViewer>(itemsControl) as ScrollViewer; 
       scrollViewer.ScrollToTop(); 
       itemsControl.ItemContainerGenerator.StatusChanged -= eventHandler; 
      } 
     }); 
     itemsControl.ItemContainerGenerator.StatusChanged += eventHandler; 
    } 
} 

और GetVisualChild के एक कार्यान्वयन

private T GetVisualChild<T>(DependencyObject parent) where T : Visual 
{ 
    T child = default(T); 
    int numVisuals = VisualTreeHelper.GetChildrenCount(parent); 
    for (int i = 0; i < numVisuals; i++) 
    { 
     Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); 
     child = v as T; 
     if (child == null) 
     { 
      child = GetVisualChild<T>(v); 
     } 
     if (child != null) 
     { 
      break; 
     } 
    } 
    return child; 
} 
7

देर जवाब की तरह इस्तेमाल किया जा सकता TargetUpdated घटना के लिए एक ईवेंट हैंडलर जोड़ने के लिए, और बाध्यकारी ItemsSource पर NotifyOnTargetUpdated=True सेट:

<ListBox x:Name="listBox" 
     ItemsSource="{Binding MySource, NotifyOnTargetUpdated=True}" 
     TargetUpdated="ListBox_TargetUpdated"/> 

और ईवेंट हैंडलर में, शीर्ष आइटम के लिए स्क्रॉल:

private void ListBox_TargetUpdated(object sender, DataTransferEventArgs e) 
{ 
    if (listBox.Items.Count > 0) 
    { 
     listBox.ScrollIntoView(listBox.Items[0]); 
    } 
} 
0

बेहतर काम करने के लिए फ्रेड्रिक Hedblad के जवाब ObservableCollection के साथ:

public static class ItemsControlAttachedProperties 
{ 
    #region ScrollToTopOnItemsSourceChange Property 

    public static readonly DependencyProperty ScrollToTopOnItemsSourceChangeProperty = 
     DependencyProperty.RegisterAttached(
      "ScrollToTopOnItemsSourceChange", 
      typeof(bool), 
      typeof(ItemsControlAttachedProperties), 
      new UIPropertyMetadata(false, OnScrollToTopOnItemsSourceChangePropertyChanged)); 

    public static bool GetScrollToTopOnItemsSourceChange(DependencyObject obj) 
    { 
     return (bool) obj.GetValue(ScrollToTopOnItemsSourceChangeProperty); 
    } 

    public static void SetScrollToTopOnItemsSourceChange(DependencyObject obj, bool value) 
    { 
     obj.SetValue(ScrollToTopOnItemsSourceChangeProperty, value); 
    } 

    static void OnScrollToTopOnItemsSourceChangePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     var itemsControl = obj as ItemsControl; 
     if (itemsControl == null) 
     { 
      throw new Exception("ScrollToTopOnItemsSourceChange Property must be attached to an ItemsControl based control."); 
     } 

     DependencyPropertyDescriptor descriptor = 
      DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(ItemsControl)); 
     if (descriptor != null) 
     { 
      if ((bool) e.NewValue) 
      { 
       descriptor.AddValueChanged(itemsControl, ItemsSourceChanged); 
      } 
      else 
      { 
       descriptor.RemoveValueChanged(itemsControl, ItemsSourceChanged); 
      } 
     } 
    } 

    static void ItemsSourceChanged(object sender, EventArgs e) 
    { 
     var itemsControl = sender as ItemsControl; 
     DoScrollToTop(itemsControl); 

     var collection = itemsControl.ItemsSource as INotifyCollectionChanged; 
     if (collection != null) 
     { 
      collection.CollectionChanged += (o, args) => DoScrollToTop(itemsControl); 
     } 
    } 

    static void DoScrollToTop(ItemsControl itemsControl) 
    { 
     EventHandler eventHandler = null; 
     eventHandler = 
      delegate 
      { 
       if (itemsControl.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) 
       { 
        var scrollViewer = GetVisualChild<ScrollViewer>(itemsControl); 
        scrollViewer.ScrollToTop(); 
        itemsControl.ItemContainerGenerator.StatusChanged -= eventHandler; 
       } 
      }; 
     itemsControl.ItemContainerGenerator.StatusChanged += eventHandler; 
    } 

    static T GetVisualChild<T>(DependencyObject parent) where T : Visual 
    { 
     T child = default(T); 
     int numVisuals = VisualTreeHelper.GetChildrenCount(parent); 
     for (var i = 0; i < numVisuals; i++) 
     { 
      var v = (Visual) VisualTreeHelper.GetChild(parent, i); 
      child = v as T ?? GetVisualChild<T>(v); 
      if (child != null) 
      { 
       break; 
      } 
     } 
     return child; 
    } 

    #endregion 
} 
0

आप नियंत्रण स्वरूपित है, तो आप कक्षों की किसी श्रेणी चयन विकल्प जो टी के रूप में चयन सूची बॉक्स में सूचीबद्ध मुर्गी। आप चयनित विकल्पों के लिंक के रूप में एक सेल भी चुनते हैं जिसमें सूची में चयन की स्थिति के आधार पर एक संख्या प्रदर्शित की जाएगी। सूची में पहले के लिए 1, दूसरे के लिए 2 आदिकोड काफी बस है: -

रेंज ("A1") सेल आप लिंक कर लिया है करने के लिए का चयन करें

चयन = 1

बदलें ("A1") और में स्थिति के लिए 1 बदलने वह सूची जो आप चुनना चाहते हैं।

एक लिंक होने वाला सेल संदर्भ दोनों तरीकों से काम करता है - यदि आप अपना चयन बदलते हैं, तो सेल में संख्या बदलती है और यदि आप सेल में संख्या बदलते हैं, तो हाइलाइट किए गए चयन में परिवर्तन होता है।

संबंधित मुद्दे