2013-11-11 2 views
1

мне нужно найти элемент внутри элемента управления содержимым:Как получить элемент внутри элемента управления содержимым

<ContentControl Content="{Binding YourChoices}" Grid.ColumnSpan="3" x:Name="ccBloodGroup"> 
       <ContentControl.ContentTemplate> 
        <DataTemplate> 
         <Grid> 
          <ComboBox x:Name="cbBloodGroup" ItemsSource="{Binding}" HorizontalAlignment="Left" Margin="10,160,0,0" VerticalAlignment="Top" Width="331" Height="45"> 
           <ComboBoxItem>A+</ComboBoxItem> 
           <ComboBoxItem>A-</ComboBoxItem> 
           <ComboBoxItem>B+</ComboBoxItem> 
           <ComboBoxItem>B-</ComboBoxItem> 
           <ComboBoxItem>O+</ComboBoxItem> 
           <ComboBoxItem>O-</ComboBoxItem> 
           <ComboBoxItem>AB+</ComboBoxItem> 
           <ComboBoxItem>AB-</ComboBoxItem> 
          </ComboBox> 
          <TextBlock x:Name="tb" Text=" Blood Type" IsHitTestVisible="False" Visibility="Hidden" HorizontalAlignment="Left" Margin="10,176,0,0" VerticalAlignment="Top"/> 
         </Grid> 
         <DataTemplate.Triggers> 
          <Trigger SourceName="cbBloodGroup" Property="SelectedItem" Value="{x:Null}"> 
           <Setter TargetName="tb" Property="Visibility" Value="Visible"/> 
          </Trigger> 
         </DataTemplate.Triggers> 
        </DataTemplate> 
       </ContentControl.ContentTemplate> 
      </ContentControl> 

Я нашел ответ на Интернет как

ComboBox cb = ccBloodGroup.ContentTemplate.FindName("cbBloodGroup", ccBloodGroup) as ComboBox; 

Но это дает мне бежать исключая время: «Эта операция действительна только для элементов, которые применяют этот шаблон».

Пожалуйста, помогите ..

+0

Вы можете использовать только то, что после того, как 'OnApplyTemplate' самого управления. Если вы хотите иметь возможность ссылаться на 'ccBloodGroup' в вашем коде позади, вы можете добавить загруженное событие для него в xaml, однако было бы лучше сказать нам, почему именно вы хотите, и какова ваша фактическая цель, потому что это а не «MVVM». – Silvermind

+0

Similiar [link] (http://stackoverflow.com/questions/5679648/why-would-this-contenttemplate-findname-throw-an-invalidoperationexception-on) - вызов this.ApplyTemplate(); перед вызовом FindName – auburg

+0

возможный дубликат [Xaml внутри ContentControl и привязка к DependencyProperty] (http://stackoverflow.com/questions/19809073/xaml-inside-contentcontrol-and-binding-to-dependencyproperty) – toroveneno

ответ

4

Этот метод поможет вам:

public T FindElementByName<T>(FrameworkElement element, string sChildName) where T : FrameworkElement 
    { 
      T childElement = null; 
      var nChildCount = VisualTreeHelper.GetChildrenCount(element); 
      for (int i = 0; i < nChildCount; i++) 
      { 
       FrameworkElement child = VisualTreeHelper.GetChild(element, i) as FrameworkElement; 

       if (child == null) 
        continue; 

       if (child is T && child.Name.Equals(sChildName)) 
       { 
        childElement = (T)child; 
        break; 
       } 

       childElement = FindElementByName<T>(child, sChildName); 

       if (childElement != null) 
        break; 
      } 
      return childElement; 
    } 

И, как я использую его, просто добавить кнопку, и на кнопку Click:

private void Button_OnClick(object sender, RoutedEventArgs e) 
    { 
     var element = FindElementByName<ComboBox>(ccBloodGroup, "cbBloodGroup"); 
    } 
+0

Awesome !! thanks :) –

+0

есть более простой или более эффективный способ сделать это? – Benni

1

В принципе, вы должны предоставить элемент, который (как говорит ошибка), имеет Template применяется. Ваш ccBloodGroup элемент управления находится внутри DataTemplate и так ясно, что на него не наложено Template.

Например, элемент, который может иметь это Template приложенные к ней было бы ContentPresenter s из элементов в YourChoices коллекции, которые используют эту DataTemplate, чтобы определить, что они выглядят как в пользовательском интерфейсе.

Вы можете узнать полную информацию, как обычно на MSDN, с подробным, например на FrameworkTemplate.FindName Method странице, но это идет что-то вроде этого ... из примера на связанной странице:

// Getting the currently selected ListBoxItem 
// Note that the ListBox must have 
// IsSynchronizedWithCurrentItem set to True for this to work 
ListBoxItem myListBoxItem = (ListBoxItem)(myListBox.ItemContainerGenerator. 
    ContainerFromItem(myListBox.Items.CurrentItem)); 

// Getting the ContentPresenter of myListBoxItem 
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem); 

// Finding textBlock from the DataTemplate that is set on that ContentPresenter 
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate; 
TextBlock myTextBlock = (TextBlock)myDataTemplate.FindName("textBlock", 
    myContentPresenter); 

// Do something to the DataTemplate-generated TextBlock 
MessageBox.Show("The text of the TextBlock of the selected list item: " 
+ myTextBlock.Text); 

Метод FindVisualChild показан на связанной странице.

+0

Извините, но я не понимаю, как эти два отдельных элемента управления обмениваются данными. :(У меня есть comboBox внутри DataTemplate и вам нужно получить к нему доступ. Также если я делаю что-то вроде этого, ComboBox myListBoxItem = (ComboBox) (cbBloodGroup.ItemContainerGenerator. ContainerFromItem (cbBloodGroup.Items.CurrentItem)); он не распознает cbBloodGroup. –

+0

Повторно прочитайте мой ответ и связанную страницу MSDN. Вы получаете 'ContentPresenter' * элемента, который использует' DataTemplate' *, а не какой-либо элемент внутри 'DataTemplate'. – Sheridan

Смежные вопросы