locked
Accessing controls in a templated control from code RRS feed

  • Question

  • I have the following templated control:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:CustomControl">
    
        <Style TargetType="local:Box">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:Box">
                        <Border>
                            <TextBox Name="Input" FontSize="40" Width="200" Height="70"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>


    And I am using it in XAML as follows:

                <local:Box x:Name="myBox" HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="White" BorderThickness="2"/>

    I want to know if it is possible to obtain the Text in the TextBox as a string to use in the code behind the files as follows or using something similar

    string Text = myBox.Input.ToString();



    Frank A


    • Edited by Frank_Ibem Wednesday, January 29, 2014 5:11 PM
    Wednesday, January 29, 2014 5:10 PM

Answers

  • I think I figured it out. Here is an example of what i did (This is supposed to allow a user enter the coordinates of a point).
    <Style TargetType="local:GUIPoint">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:GUIPoint">
                        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
                            <TextBlock Style="{StaticResource SubheaderTextBlockStyle}" Text="{TemplateBinding Display}"
                                       VerticalAlignment="Center" HorizontalAlignment="Center" Margin="20" FontSize="40"/>
                            <TextBlock Text="(" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"/>
                            <TextBox FontSize="40" VerticalAlignment="Center" HorizontalAlignment="Center"
                                     Margin="20" Name="X"/>
                            <TextBlock Text="," VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"/>
                            <TextBox FontSize="40" VerticalAlignment="Center" HorizontalAlignment="Center"
                                     Margin="20" Name="Y"/>
                            <TextBlock Text="," VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"/>
                            <TextBox FontSize="40" VerticalAlignment="Center" HorizontalAlignment="Center"
                                     Margin="20" Name="Z"/>
                            <TextBlock Text=")" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"/>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    Then, in the code behind for the GUIPoint, I created several dependency property and set them to be updated each time the TextBoxes' contents were changed as follows (snippet for one coordinate)
    TextBox first;
    /* I skipped the constructor */
    
    public double? X
            {
                get { return (double?)GetValue(XProperty); }
                set { SetValue(XProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for X.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty XProperty =
                DependencyProperty.Register("X", typeof(double?), typeof(GUIPoint), new PropertyMetadata(null));
    
    protected override void OnApplyTemplate()
            {
                first = GetTemplateChild("X") as TextBox;
                ...
    
                first.TextChanged += OnTextChanged;
                ...
    
                base.OnApplyTemplate();
            }
    
    private void OnTextChanged(object sender, TextChangedEventArgs e)
            {
                double value;
                if((sender as TextBox) == first)
                {
                    if (double.TryParse(first.Text, out value))
                        X = value;
                    else
                        X = null;
                }
    
                ...
            }
    The GetTemplateChild was what I needed (Refer to Programming Windows, 6th Edition, Charles Petzold). This may not be the neatest code, but I needed to see it work.
    :

    Frank A


    • Edited by Frank_Ibem Thursday, January 30, 2014 3:09 AM
    • Marked as answer by Frank_Ibem Monday, February 10, 2014 8:11 PM
    Thursday, January 30, 2014 3:09 AM

All replies

  • What is box? I'd probably set up the text as a property on "box" and then bind to it. If you want the line you give then you could export the Input field as a property, but that ties the view to the implementation more tightly than is necessary. --Rob
    Wednesday, January 29, 2014 11:21 PM
    Moderator
  • I think I figured it out. Here is an example of what i did (This is supposed to allow a user enter the coordinates of a point).
    <Style TargetType="local:GUIPoint">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:GUIPoint">
                        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
                            <TextBlock Style="{StaticResource SubheaderTextBlockStyle}" Text="{TemplateBinding Display}"
                                       VerticalAlignment="Center" HorizontalAlignment="Center" Margin="20" FontSize="40"/>
                            <TextBlock Text="(" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"/>
                            <TextBox FontSize="40" VerticalAlignment="Center" HorizontalAlignment="Center"
                                     Margin="20" Name="X"/>
                            <TextBlock Text="," VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"/>
                            <TextBox FontSize="40" VerticalAlignment="Center" HorizontalAlignment="Center"
                                     Margin="20" Name="Y"/>
                            <TextBlock Text="," VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"/>
                            <TextBox FontSize="40" VerticalAlignment="Center" HorizontalAlignment="Center"
                                     Margin="20" Name="Z"/>
                            <TextBlock Text=")" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"/>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    Then, in the code behind for the GUIPoint, I created several dependency property and set them to be updated each time the TextBoxes' contents were changed as follows (snippet for one coordinate)
    TextBox first;
    /* I skipped the constructor */
    
    public double? X
            {
                get { return (double?)GetValue(XProperty); }
                set { SetValue(XProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for X.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty XProperty =
                DependencyProperty.Register("X", typeof(double?), typeof(GUIPoint), new PropertyMetadata(null));
    
    protected override void OnApplyTemplate()
            {
                first = GetTemplateChild("X") as TextBox;
                ...
    
                first.TextChanged += OnTextChanged;
                ...
    
                base.OnApplyTemplate();
            }
    
    private void OnTextChanged(object sender, TextChangedEventArgs e)
            {
                double value;
                if((sender as TextBox) == first)
                {
                    if (double.TryParse(first.Text, out value))
                        X = value;
                    else
                        X = null;
                }
    
                ...
            }
    The GetTemplateChild was what I needed (Refer to Programming Windows, 6th Edition, Charles Petzold). This may not be the neatest code, but I needed to see it work.
    :

    Frank A


    • Edited by Frank_Ibem Thursday, January 30, 2014 3:09 AM
    • Marked as answer by Frank_Ibem Monday, February 10, 2014 8:11 PM
    Thursday, January 30, 2014 3:09 AM