2008-10-03 11 views
26

मेरे पास एक सूची बॉक्स है जो हाल ही में आइटमों की एक विस्तृत सूची प्रदर्शित कर रहा था। मैं सूची में ListBoxItem होस्टिंग "चीज़" को पुनर्प्राप्त करने के लिए myList.ItemContainerGenerator.ConainerFromItem (चीज़) का उपयोग करने में सक्षम था।ItemContainerGenerator.ContainerFromItem समूहबद्ध सूची के साथ कैसे काम करता है?

इस हफ्ते मैंने ListBox को थोड़ा सा संशोधित किया है जिसमें संग्रहव्यूसोर्स है कि यह इसके आइटमों के लिए बाध्य करता है समूहिंग सक्षम है। अब ListBox के भीतर आइटम अच्छे शीर्षलेख के नीचे समूहित हैं।

हालांकि, ऐसा करने के बाद, ItemContainerGenerator.ContainerFromItem ने काम करना बंद कर दिया है - यह सूची बॉक्स में मुझे पता है कि आइटम के लिए भी शून्य वापस आती है। हेक - ContainerFromIndex (0) कई आइटमों के साथ सूची बॉक्स पॉप्युलेट होने पर भी शून्य वापस आ रहा है!

मैं लिस्टबॉक्स से एक सूची बॉक्स को कैसे प्राप्त करूं जो समूहबद्ध वस्तुओं को प्रदर्शित कर रहा है?

संपादित करें: यहां एक ट्रिम किए गए उदाहरण के लिए एक्सएएमएल और कोड-बैक है। यह एक NullReferenceException उठाता है क्योंकि ContainerFromIndex (1) सूची में चार आइटम होने के बावजूद शून्य लौट रहा है।

XAML:

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase" 
    Title="Window1"> 

    <Window.Resources> 
     <XmlDataProvider x:Key="myTasks" XPath="Tasks/Task"> 
      <x:XData> 
       <Tasks xmlns=""> 
        <Task Name="Groceries" Type="Home"/> 
        <Task Name="Cleaning" Type="Home"/> 
        <Task Name="Coding" Type="Work"/> 
        <Task Name="Meetings" Type="Work"/> 
       </Tasks> 
      </x:XData> 
     </XmlDataProvider> 

     <CollectionViewSource x:Key="mySortedTasks" Source="{StaticResource myTasks}"> 
      <CollectionViewSource.SortDescriptions> 
       <scm:SortDescription PropertyName="@Type" /> 
       <scm:SortDescription PropertyName="@Name" /> 
      </CollectionViewSource.SortDescriptions> 

      <CollectionViewSource.GroupDescriptions> 
       <PropertyGroupDescription PropertyName="@Type" /> 
      </CollectionViewSource.GroupDescriptions> 
     </CollectionViewSource> 
    </Window.Resources> 

    <ListBox 
     x:Name="listBox1" 
     ItemsSource="{Binding Source={StaticResource mySortedTasks}}" 
     DisplayMemberPath="@Name" 
     > 
     <ListBox.GroupStyle> 
      <GroupStyle> 
       <GroupStyle.HeaderTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding Name}"/> 
        </DataTemplate> 
       </GroupStyle.HeaderTemplate> 
      </GroupStyle> 
     </ListBox.GroupStyle> 
    </ListBox> 
</Window> 

सीएस:

public Window1() 
{ 
    InitializeComponent(); 
    listBox1.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged; 
} 

void ItemContainerGenerator_StatusChanged(object sender, EventArgs e) 
{ 
    if (listBox1.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) 
    { 
     listBox1.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged; 

     var i = listBox1.ItemContainerGenerator.ContainerFromIndex(1) as ListBoxItem; 

     // select and keyboard-focus the second item 
     i.IsSelected = true; 
     i.Focus(); 
    } 
} 
+0

तुम क्या कर रहे देना कंटेनर के साथ? क्या आप संभवतः पिछले कोड के काम पर क्या संभवतः काम कर सकते हैं? कंटेनर प्राप्त करने के कुछ तरीके हैं ... यह सिर्फ इस बात पर निर्भर करता है कि आप इसके साथ क्या करना चाहते हैं? – rudigrobler

उत्तर

35

आप सुनने के लिए है और प्रतिक्रिया तक पहुँचने की कोशिश करो ItemsGenerator.StatusChanged पर ईवेंट और प्रतीक्षा करें जब तक कि आप ContainerFromElement के साथ उन तक पहुंचने से पहले आइटमकंटनर उत्पन्न नहीं हो जाते।


आगे सर्च कर रहे हैं, मैं कोई है जो एक ही समस्या है से a thread in the MSDN forum पाया है। यह WPF में एक बग प्रतीत होता है, जब किसी के पास समूह स्टाइल सेट होता है। समाधान प्रतिपादन प्रक्रिया के बाद ItemGenerator की पहुंच को पंप करना है। नीचे आपके प्रश्न के लिए कोड है। मैं इस की कोशिश की, और यह काम करता है:

void ItemContainerGenerator_StatusChanged(object sender, EventArgs e) 
    { 
     if (listBox1.ItemContainerGenerator.Status 
      == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) 
     { 
      listBox1.ItemContainerGenerator.StatusChanged 
       -= ItemContainerGenerator_StatusChanged; 
      Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input, 
       new Action(DelayedAction)); 
     } 
    } 

    void DelayedAction() 
    { 
     var i = listBox1.ItemContainerGenerator.ContainerFromIndex(1) as ListBoxItem; 

     // select and keyboard-focus the second item 
     i.IsSelected = true; 
     i.Focus(); 
    } 
+0

हाँ, मैं यह कर रहा हूँ। मैं कुछ हफ्तों के साथ अगले सप्ताह के शुरुआती प्रश्न को अपडेट कर दूंगा। –

+0

बस खुद को बाहर करने की कोशिश की।इस सप्ताह के अंत में मुझे परेशानी में कुछ मदद मिली है। –

+0

बहुत बढ़िया - धन्यवाद डेविड। मुझे अभी तक इसका परीक्षण करने का मौका नहीं मिला है, लेकिन मैं इसे अभी "जवाब" के रूप में स्वीकार करूंगा। –

0

'बात' से VisualTree को पार्स जब तक आप एक ListBoxItem प्रकार

+0

जॉबी - इस मामले में "चीज" एक दृश्य तत्व नहीं है - यह एक व्यावसायिक वस्तु का एक उदाहरण है। एक IList का हिस्सा जो ListBox के आइटम स्रोत से जुड़ा हुआ है। क्या मैं उस परिदृश्य के तहत जो वर्णन कर रहा हूं वह कर सकता हूं? –

+0

हाँ आपको मिल गया। स्पष्टीकरण के लिए धन्यवाद। आपके पीछे कोड के किस हिस्से से ऐसा करने की कोशिश कर रहे हैं? किसी भी डेटा टेम्पलेट क्लिक करें या किसी अन्य घटना हैंडलर में? –

+0

जब पृष्ठ (यह एक नेविगेशन-शैली अनुप्रयोग है) लोड करता है, तो मैं एक विशिष्ट तत्व पर कीबोर्ड फ़ोकस सेट करना चाहता हूं। तो लोडेड इवेंट हैंडलर में। –

0

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

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" ..../> 
संबंधित मुद्दे