0

I use this method to list all the buttons of a usercontrol:

private static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
    if (depObj != null)
    {
        int NbChild = VisualTreeHelper.GetChildrenCount(depObj);

        for (int i = 0; i < NbChild; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

            if (child != null && child is T)
            {
                yield return (T)child;
            }

            foreach (T childNiv2 in FindVisualChildren<T>(child))
            {
                yield return childNiv2;
            }
        }
    }
}
public static void ImplementShortCut(ContentControl page)
{
  List<Button> ListButton = new List<Button>();
  ListButton = FindVisualChildren<Button>(page).ToList();
  ....
}

It's working well except for buttons inside DataGridTemplateColumn.CellTemplate

<DataGridTemplateColumn>                    
<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <StackPanel>
            <Button x:Name="Btn_Edit"
                    Click="Btn_EditTest_Click"/>
        </StackPanel>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

'VisualTreeHelper.GetChild' does not seem to be able to find the controls in datagrid items.

Marc
  • 107
  • 8
  • Should work. What is "page" and where do you call the method? – mm8 Jun 29 '17 at 10:04
  • 'page' is a UserControl, the method is called in load method (TestPage_Loaded), Itself called in the constructor of 'page' (this.Loaded += TestPage_Loaded;) But i haven't any problem for button outside the datagrid!! – Marc Jun 29 '17 at 10:17
  • That's ununderstandable...please post your code. Is the DataGrid located in "page"? – mm8 Jun 29 '17 at 10:20
  • 1
    Because on Loaded event the control is loaded, but not the template (at least - that is not guaranteed). Try calling in: public override void OnApplyTemplate(); – Maciek Świszczowski Jun 29 '17 at 10:46
  • Using: public override void OnApplyTemplate (); the list 'ListButton' return 0 items, because it's called before Load methode! – Marc Jun 29 '17 at 11:22

2 Answers2

0

My class

public class ShortCutUtils
{
  public static void ImplementShortCut(ContentControl page)
  {
     List<Button> ListButton = new List<Button>();
     ListButton = FindVisualChildren<Button>(page).ToList();
      ...
  }


 private static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
 {
 if (depObj != null)
  {
    int NbChild = VisualTreeHelper.GetChildrenCount(depObj);

    for (int i = 0; i < NbChild; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

        if (child != null && child is T)
        {
            yield return (T)child;
        }

        foreach (T childNiv2 in FindVisualChildren<T>(child))
        {
            yield return childNiv2;
        }
    }
  }
 }
}

TestPage XAML

            <DataGrid Grid.Row="0" x:Name="Dg_Test" 
                Margin="2"
                AutoGenerateColumns="False"
                SelectedCellsChanged="dg_Test_SelectionChanged"
                SelectionMode="Single"
                MouseLeftButtonDown="Dg_TestMouseClick"
                RowDetailsVisibilityMode="{Binding RowDetailsVisible}"
                ScrollViewer.VerticalScrollBarVisibility="Visible"
                Style="{StaticResource DatagridDesktopStyle}">

                <DataGrid.Columns>
                    ...
                    <DataGridTemplateColumn Width="auto" IsReadOnly="True" Header="">
                        DataGridTemplateColumn.HeaderTemplate>
                         ...
                        </DataGridTemplateColumn.HeaderTemplate>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel>
                                    <Button x:Name="Btn_Edit"
                                            Click="Btn_EditTest_Click"/>
                                </StackPanel>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
        </DataGrid>

TestPage Code

public partial class TestPage : UserControl
{
  public TestPage()
  {
  InitializeComponent();
  this.Loaded += TestListPage_Loaded;
  this.DataContext = this;
  } 


  private async void TestListPage_Loaded(object sender, RoutedEventArgs e)
  {
   ShortCutUtils.ImplementShortCut(this);
  }
}
Marc
  • 107
  • 8
0

As assumed swiszcz, all controls are not finished being loaded when calling the 'ShortCutUtils.ImplementShortCut (this)' method at the end of 'Load'. To remedy this I therefore placed this method in a low-priority 'Invoke'

Application.Current.Dispatcher.Invoke(() =>
 {ShortCutUtils.ImplementShortCut (this);
 }, DispatcherPriority.Render);

And it works fine! Thank you so much

Marc
  • 107
  • 8