2013-06-08 10 views

risposta

12

Per trovare un controllo in una colonna DataGrid modello, si dovrebbe usare FindChild():

public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject 
    { 
     if (parent == null) 
     { 
      return null; 
     } 

     T foundChild = null; 

     int childrenCount = VisualTreeHelper.GetChildrenCount(parent); 

     for (int i = 0; i < childrenCount; i++) 
     { 
      var child = VisualTreeHelper.GetChild(parent, i); 
      T childType = child as T; 

      if (childType == null) 
      { 
       foundChild = FindChild<T>(child, childName); 

       if (foundChild != null) break; 
      } 
      else 
       if (!string.IsNullOrEmpty(childName)) 
       { 
        var frameworkElement = child as FrameworkElement; 

        if (frameworkElement != null && frameworkElement.Name == childName) 
        { 
         foundChild = (T)child; 
         break; 
        } 
        else 
        { 
         foundChild = FindChild<T>(child, childName); 

         if (foundChild != null) 
         { 
          break; 
         } 
        } 
       } 
       else 
       { 
        foundChild = (T)child; 
        break; 
       } 
     } 

     return foundChild; 
    } 

Per esempio io ho questa colonna modello nella MyDataGrid:

<DataGridTemplateColumn Width="1.5*" IsReadOnly="False"> 
    <DataGridTemplateColumn.Header> 
     <TextBlock Text="Sample" ToolTip="{Binding Path=Text, RelativeSource={RelativeSource Self}}" FontSize="14" /> 
    </DataGridTemplateColumn.Header> 

    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <TextBlock x:Name="MyTextBlock" Text="Hello!" /> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn> 

accesso dal codice , è possibile:

TextBlock MyTextBlock = FindChild<TextBlock>(MyDataGrid, "MyTextBlock"); 

MessageBox.Show(MyTextBlock.Text); 

Nota: Utilizzare sempre FindChild solo quando il controllo sarà completamente caricato, altrimenti non lo troverà e restituirà null. In questo caso, ho messo questo codice in caso ContentRendered (finestra) che dice che tutti i contenuti della finestra di caricare correttamente (anche l'evento non MyDataGrid_Loaded hanno accesso a MyTextBlock, perché non è ancora carico):

private void Window_ContentRendered(object sender, EventArgs e) 
    { 
     TextBlock MyTextBlock = FindChild<TextBlock>(MyDataGrid, "MyTextBlock"); 

     MessageBox.Show(MyTextBlock.Text); 
    } 

Edit1:

per accedere al controllo della riga selezionata aggiungere evento SelectionChanged a DataGrid in cui funzionamento, che darà una riga selezionata:

private void MyDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     try 
     { 
      var row_list = GetDataGridRows(MyDataGrid); 

      foreach (DataGridRow single_row in row_list) 
      { 
       if (single_row.IsSelected == true) 
       { 
        TextBlock MyTextBlock = FindChild<TextBlock>(single_row, "MyTextBlock"); 

        MessageBox.Show(MyTextBlock.Text); 
       } 
      } 
     } 

     catch 
     { 
      throw new Exception("Can't get access to DataGridRow"); 
     } 
    } 

elenco di GetDataGridRows():

public IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid) 
    { 
     var itemsSource = grid.ItemsSource as IEnumerable; 

     if (null == itemsSource) 
     { 
      yield return null; 
     } 

     foreach (var item in itemsSource) 
     { 
      var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow; 

      if (null != row) 
      { 
       yield return row; 
      } 
     } 
    } 

EDIT2:

Per ottenere TUTTI le voci ho riscritto la funzione FindChild():

public static void FindChildGroup<T>(DependencyObject parent, string childName, ref List<T> list) where T : DependencyObject 
    { 
     // Checks should be made, but preferably one time before calling. 
     // And here it is assumed that the programmer has taken into 
     // account all of these conditions and checks are not needed. 
     //if ((parent == null) || (childName == null) || (<Type T is not inheritable from FrameworkElement>)) 
     //{ 
     // return; 
     //} 

     int childrenCount = VisualTreeHelper.GetChildrenCount(parent); 

     for (int i = 0; i < childrenCount; i++) 
     { 
      // Get the child 
      var child = VisualTreeHelper.GetChild(parent, i); 

      // Compare on conformity the type 
      T child_Test = child as T; 

      // Not compare - go next 
      if (child_Test == null) 
      { 
       // Go the deep 
       FindChildGroup<T>(child, childName, ref list); 
      } 
      else 
      { 
       // If match, then check the name of the item 
       FrameworkElement child_Element = child_Test as FrameworkElement; 

       if (child_Element.Name == childName) 
       { 
        // Found 
        list.Add(child_Test); 
       } 

       // We are looking for further, perhaps there are 
       // children with the same name 
       FindChildGroup<T>(child, childName, ref list); 
      } 
     } 

     return; 
    } 

Calling questa nuova funzione:

private void Window_ContentRendered(object sender, EventArgs e) 
    { 
     // Create the List 
     List<TextBlock> list = new List<TextBlock>(); 

     // Find all elements 
     FindChildGroup<TextBlock>(MyDataGrid, "MyTextBlock", ref list); 
     string text = ""; 

     // Print 
     foreach (TextBlock elem in list) 
     { 
      text += elem.Text + "\n"; 
     } 

     MessageBox.Show(text, "Text in TextBlock"); 
    } 

In generale, questa pratica non è il migliore ... per ottenere gli elementi (quali tutti o selezionato), è possibile contattare direttamente alla lista che memorizza i dati (come ObservableCollection). Inoltre, sono eventi utili come PropertyChanged.

+0

Sono di fronte allo stesso problema della persona nella discussione a cui mi sono collegato. Non riesco a trovare un modo per farlo funzionare su ogni riga. Solo uno. Come farlo funzionare sulla riga selezionata? – acosta

+1

Vedi la mia modifica. –

+0

Hmm .. il codice per far funzionare tutti, ma quello dalla prima modifica getta solo l'eccezione che non può accedere a DataGridRow – acosta

Problemi correlati