2011-03-03 19 views
13

मेरे पास एक सूची बॉक्स है जिसमें एक आइटम टेम्पलेट 2 स्टैकपैनल्स के साथ है। दूसरे स्टैकपैनल में एक टेक्स्टबॉक्स है जिसे मैं एक्सेस करना चाहता हूं। (इसे सत्य के लिए दृश्यता बदलें और उपयोगकर्ता इनपुट स्वीकार करें) ट्रिगर SelectionChangedEvent होना चाहिए। इसलिए, यदि कोई उपयोगकर्ता ListBoxItem पर क्लिक करता है, तो टेक्स्टब्लॉक अदृश्य हो जाता है और टेक्स्टबॉक्स दिखाई देता है।DataTemplate के साथ किसी सूची बॉक्स में किसी विशिष्ट आइटम को कैसे एक्सेस करें?

XAML कोड:

<ListBox Grid.Row="1" Name="ContactListBox" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ItemsSource="{Binding Contacts}" Margin="0,36,0,0" SelectionChanged="ContactListBox_SelectionChanged"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal" Margin="0,0,0,0"> 
         <toolkit:ContextMenuService.ContextMenu> 
          <toolkit:ContextMenu> 
           <toolkit:MenuItem Header="Edit Contact" Click="ContactMenuItem_Click"/> 
           <toolkit:MenuItem Header="Delete Contact" Click="ContactMenuItem_Click"/> 
          </toolkit:ContextMenu> 
         </toolkit:ContextMenuService.ContextMenu> 

         <Grid> 
          <Rectangle Fill="{StaticResource PhoneAccentBrush}" 
              Width="72" Height="72"> 
           <Rectangle.OpacityMask> 
            <ImageBrush ImageSource="/Images/defaultContactImage.png" Stretch="UniformToFill"/> 
           </Rectangle.OpacityMask> 
          </Rectangle> 
         </Grid> 
         <StackPanel> 
          <TextBox Text="{Binding Name}" TextWrapping="Wrap" Visibility="Collapsed"/> 
          <TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" /> 
          <TextBlock Text="{Binding Number}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextAccentStyle}"/> 
         </StackPanel> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 

मुझे लगता है कि वहाँ इस को हल करने के कई तरीके हैं, लेकिन कुछ भी मैं काम करने की कोशिश की।

मेरे वर्तमान दृष्टिकोण इस

private void ContactListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     ListBoxItem listBoxItem = ContactListBox.SelectedItem as ListBoxItem; 

     DataTemplate listBoxTemplate = listBoxItem.ContentTemplate; 

     // How to access the DataTemplate content? 

     StackPanel outerStackPanel = listBoxTemplate.XXX as StackPanel; 

     StackPanel innerStackPanel = outerStackPanel.Children[1] as StackPanel; 

     TextBox nameBox = innerStackPanel.Children[0] as TextBox; 
     TextBlock nameBlock = innerStackPanel.Children[1] as TextBlock; 


     nameBox.Visibility = System.Windows.Visibility.Visible; 
     nameBlock.Visibility = System.Windows.Visibility.Collapsed; 

    } 
+1

मुझे समाधान पसंद है, लेकिन अगर मेरे पास कुछ टेक्स्टब्लॉक हैं और मैं पहले लेकिन पूर्व को दृश्यमान/संक्षिप्त नहीं करना चाहता हूं। दूसरा या तीसरा? दूसरे शब्दों में निर्दिष्ट नाम के साथ सूची बॉक्स नियंत्रण में कैसे पहुंचे? – dargod

+0

@ sust86 सूची में ** XXX ** क्या है BoxTemplate.XXX? – ROMAN

+0

यदि आप नाम से पुन: प्रयास करना चाहते हैं, तो इस समाधान का उपयोग करें: http: // stackoverflow।com/a/1759923/3934111 –

उत्तर

27

आपकी मदद के लोगों के लिए धन्यवाद !! आखिरकार मुझे मिल गया। VisualTreeHelper के साथ समस्या हल हो गई। क्या एक महान समारोह ^^

private void ContactListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     if (ContactListBox.SelectedIndex == -1) 
      return; 

     currentSelectedListBoxItem = this.ContactListBox.ItemContainerGenerator.ContainerFromIndex(ContactListBox.SelectedIndex) as ListBoxItem; 

     if (currentSelectedListBoxItem == null) 
      return; 

     // Iterate whole listbox tree and search for this items 
     TextBox nameBox = helperClass.FindDescendant<TextBox>(currentSelectedListBoxItem); 
     TextBlock nameBlock = helperClass.FindDescendant<TextBlock>(currentSelectedListBoxItem); 

helperFunction

public T FindDescendant<T>(DependencyObject obj) where T : DependencyObject 
    { 
     // Check if this object is the specified type 
     if (obj is T) 
      return obj as T; 

     // Check for children 
     int childrenCount = VisualTreeHelper.GetChildrenCount(obj); 
     if (childrenCount < 1) 
      return null; 

     // First check all the children 
     for (int i = 0; i < childrenCount; i++) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(obj, i); 
      if (child is T) 
       return child as T; 
     } 

     // Then check the childrens children 
     for (int i = 0; i < childrenCount; i++) 
     { 
      DependencyObject child = FindDescendant<T>(VisualTreeHelper.GetChild(obj, i)); 
      if (child != null && child is T) 
       return child as T; 
     } 

     return null; 
    } 
+0

ओह यह होना चाहिए: मुझे समाधान पसंद है, लेकिन अगर मेरे पास कुछ टेक्स्टब्लॉक हैं और मैं पहले लेकिन पूर्व को दृश्यमान/संक्षिप्त नहीं करना चाहता हूं। दूसरा या तीसरा? दूसरे शब्दों में निर्दिष्ट नाम के साथ सूची बॉक्स नियंत्रण में कैसे पहुंचे? – dargod

2

मैं तुम्हें एक पूरा जवाब नहीं दे सकता की तरह दिखता है ...

लेकिन मुझे लगता है कि आप किसी भी के बच्चों के माध्यम से पुनरावृति करने के लिए उपयोग कर सकते हैं VisualTreeHelper नियंत्रण http://blogs.msdn.com/b/kmahone/archive/2009/03/29/visualtreehelper.aspx

हालांकि, जिस प्रभाव के लिए आप खोज रहे हैं, उसके लिए मुझे लगता है कि चयनित इटैम शैली का उपयोग करना एक बेहतर समाधान हो सकता है - उदाहरण के लिए यह आलेख देखें - http://joshsmithonwpf.wordpress.com/2007/07/30/customizing-the-selected-item-in-a-listbox/

+0

विजुअल ट्रीहेल्पर के साथ आपके संकेत के लिए धन्यवाद! :) – sust86

+0

मुझे धन्यवाद देने के लिए ... ऊपर की ओर हिट करें :) और मुझे सच में लगता है कि आपको कोड का उपयोग करने के बजाय चयनित इटैम शैली का उपयोग करके अपना प्रभाव करना चाहिए - लंबे समय तक इसका सबसे अच्छा तरीका (मुझे लगता है) – Stuart

+1

मैंने कोशिश की ... "वोट अप को 15 प्रतिष्ठा की आवश्यकता है" ठीक है, मैं निश्चित रूप से सीखने जा रहा हूं कि ब्लेंड के साथ कैसे काम करना है। लेकिन विंडोज फोन प्रोग्रामिंग दृश्य में नया हूं और अभी भी यह पता लगाने की कोशिश कर रहा हूं कि यह सब कुछ कैसे काम करता है। मुझे बस और समय चाहिए =) – sust86

1

ItemContainerGenerator का उपयोग करें।

private void ContactListBox_SelectionChanged 
    (object sender, SelectionChangedEventArgs e) 
{ 
    if (e.AddedItems.Count == 1) 
    { 
    var container = (FrameworkElement)ContactListBox.ItemContainerGenerator. 
         ContainerFromItem(e.AddedItems[0]); 

    StackPanel sp = container.FindVisualChild<StackPanel>(); 
    TextBox tbName = (TextBox) sp.FindName("tbName"); 
    TextBlock lblName = (TextBlock)sp.FindName("lblName"); 
    TextBlock lblNumber = (TextBlock)sp.FindName("lblNumber"); 
    } 
} 
+1

ग्रेट, मैं इस समाधान का उपयोग करना चाहता हूं। हालांकि, स्पष्ट रूप से एक फ्रेमवर्क एलिमेंट में "FindVisualChild" की परिभाषा नहीं है। शायद इसका कारण यह है कि मैं विंडोज फोन 7 के लिए चांदी की रोशनी के साथ काम कर रहा हूं ?! अभी भी इस समस्या को हल करने का तरीका जानने का प्रयास कर रहा है। हो सकता है कि VisualTreeHelper मदद कर सकता है =) TY वैसे भी – sust86

1

के बाद से DataTemplate कोड में कई बार इस्तेमाल किया जा सकता है कि एक सामान्य टेम्पलेट है, वहाँ यह नाम से (: नाम = "numberTextBox" एक्स) तक पहुँचने के लिए कोई रास्ता नहीं है।

मैंने नियंत्रणों का संग्रह करके इसी तरह की समस्या हल की - जबकि सूची बॉक्स पॉप्युलेट कर रहा था, मैं संग्रह में टेक्स्टबॉक्स नियंत्रण जोड़ता हूं।

string text = myCollectionOfTextBoxes[listbox.SelectedIndex].Text; 

जब तक मुझे एक बेहतर आत्मा - टैग संपत्ति नहीं मिली। अपने ListboxItem में आप नाम

Tag="{Binding Name}" 

को टैग संपत्ति के लिए बाध्य है और यह

तक पहुँचने के लिए
ListBoxItem listBoxItem = ContactListBox.SelectedItem as ListBoxItem; 

string name = listBoxItem.Tag.ToString(); 
+0

मुझे यकीन नहीं है कि मैं इस दृष्टिकोण को पूरी तरह से समझता हूं। लेकिन यह केवल तब उपयोगी होगा जब मुझे टेक्स्टबॉक्स/टेक्स्टब्लॉक के टेक्स्ट को जानने की आवश्यकता हो। टेक्स्टबॉक्स पर ध्यान केंद्रित करने और इस समाधान के साथ उपयोगकर्ता इनपुट स्वीकार करने का कोई तरीका नहीं है, है ना? – sust86

+0

तो क्या आप बटन का व्यवहार करना चाहते हैं? http://forums.create.msdn.com/forums/t/69801.aspx इस पर एक नज़र डालें। –

3

इस संपादित समारोह के साथ आप भी नाम से नियंत्रण के लिए खोज कर सकते हैं (VB.NET से परिवर्तित):

public T FindDescendantByName<T>(DependencyObject obj, string objname) where T : DependencyObject 
{ 
    string controlneve = ""; 

    Type tyype = obj.GetType(); 
    if (tyype.GetProperty("Name") != null) { 
     PropertyInfo prop = tyype.GetProperty("Name"); 
     controlneve = prop.GetValue((object)obj, null); 
    } else { 
     return null; 
    } 

    if (obj is T && objname.ToString().ToLower() == controlneve.ToString().ToLower()) { 
     return obj as T; 
    } 

    // Check for children 
    int childrenCount = VisualTreeHelper.GetChildrenCount(obj); 
    if (childrenCount < 1) 
     return null; 

    // First check all the children 
    for (int i = 0; i <= childrenCount - 1; i++) { 
     DependencyObject child = VisualTreeHelper.GetChild(obj, i); 
     if (child is T && objname.ToString().ToLower() == controlneve.ToString().ToLower()) { 
      return child as T; 
     } 
    } 

    // Then check the childrens children 
    for (int i = 0; i <= childrenCount - 1; i++) { 
     string checkobjname = objname; 
     DependencyObject child = FindDescendantByName<T>(VisualTreeHelper.GetChild(obj, i), objname); 
     if (child != null && child is T && objname.ToString().ToLower() == checkobjname.ToString().ToLower()) { 
      return child as T; 
     } 
    } 

    return null; 
} 
संबंधित मुद्दे

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