Caliphe Caliphe - 2 months ago 30
C# Question

Get control from style within style

I have a style :

<Style TargetType="TextBox" x:Key="TextBoxStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Button x:Name="Button1" />
</Grid>
<ControlTemplate/>
</Setter.Value>
</Setter>
</Style>

<Style TargetType="local:MyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl">
<Grid>
...
<TextBox x:Name="TextBox1" Style="{StaticRessource TextBoxStyle}/>
...
</Grid>
<ControlTemplate/>
</Setter.Value>
</Setter>
</Style>


the problem is that I can't get the "Button1", code behind :

public class MyControl : ItemsSource
{

private TextBox _textBox1;
private Button _button1;

protected override void OnApplyTemplate()
{
_textBox1 = (TextBox)GetTemplateChild("TextBox1");

base.OnApplyTemplate();

}

}


In wpf i can do :

_button1 = (Button)_textBox1.Template.FindName("Button1");


But the "FindName()" method does't exist in uwp, so how can i get the Button1 ?

Thank's !

EDIT :

If we look at AutoSuggestBox's style we have the style AutoSuggestBox and the AutoSuggestBoxTextBoxStyle. The autosuggestbox raise the event "QuerySubmitted" which is from the button "QueryButton", which is in the AutoSuggestBoxTextBoxStyle. So he can have access to the button right ?

Answer

According to your code, you created a Templated Control. GetTemplateChild method is used for get the child element from the template. The above code snap is inside MyControl class and we can get child element from the MyControl template as you did to find the TextBox1 . But for Button1, it is not inside the template of MyControl(it is in template of _textbox1), it seems like we cannot get it.

so how can i get the Button1 ?

We can get the Button1 after MyControl rendered by VisualTreeHelper. Here is a demo about creating a MyControl in MainPage and then get the Button1 element by VisualTreeHelper.

Xaml Code

<local:MyControl x:Name="mycontrol" Height="200" Width="200"></local:MyControl>   
<Button x:Name="getbutton1" Click='getbutton1_Click' Content="Get button1"></Button>

Code behind

  private static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
  {
      if (depObj != null)
      {
          for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
          {
              DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
              if (child != null && child is T)
              {
                  yield return (T)child;
              }

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

  private void getbutton1_Click(object sender, RoutedEventArgs e)
  {
      Button _button1 = null;
      IEnumerable<Button> buttons = FindVisualChildren<Button>(mycontrol);
      foreach (var _button in buttons)
      {
          if (_button.Name == "Button1")
          {
             _button1 = _button;
          }
      }
      System.Diagnostics.Debug.WriteLine(_button1.Content);
  }

So he can have access to the button right ?

In that case, please check the QueryButton in the style, it is in a Grid, not a TextBox. And the 'textbox' you saw in the AutoSuggestBox is actually a ContentControl which is inside same Grid with QueryButton. So the button can be got.