Poma Poma - 9 days ago 9
C# Question

How to declare event handlers inside ControlTemplate?

I have the following

ControlTemplate
:

<ControlTemplate>
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Left" Width="400">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="18" />
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="45" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="1" Template="{StaticResource watermark}" HorizontalAlignment="Stretch" Margin="4,0,0,4" Tag="Number" />
<TextBox Grid.Column="2" Template="{StaticResource watermark}" HorizontalAlignment="Stretch" Margin="4,0,0,4" Tag="Login" />
<TextBox Grid.Column="3" Template="{StaticResource watermark}" HorizontalAlignment="Stretch" Margin="4,0,0,4" Tag="Password" />
<Button Grid.Column="4" HorizontalAlignment="Stretch" Content="Add" Margin="4,0,0,4" Click="AddUser_Click"/>
</Grid>
</ControlTemplate>


How should I write
AddUser_Click
to get access to textboxes
Text
properties?

upd: just to make it clear. I know how to connect
Click
event handler here. The question is how to read contents of textboxes in it since I cant give them name because they are in a template.

Answer Source

If you have access to the templatedparent (SelectedItem, FindVisualParent etc.) you can do this if you apply Names to the TextBoxes. Example if ControlTemplate is for ComboBoxItem.

private void AddUser_Click(object sender, RoutedEventArgs e)
{
    ComboBoxItem comboBoxItem = GetVisualParent<ComboBoxItem>(button);
    TextBox textBox = comboBoxItem.Template.FindName("numberTextBox", comboBoxItem) as TextBox;
    //...
}

Another way to get the TextBoxes within the ControlTemplate would be to use the Visual Tree. Something like this

private void AddUser_Click(object sender, RoutedEventArgs e)
{
    Button button = sender as Button;
    Grid parentGrid = GetVisualParent<Grid>(button);
    List<TextBox> textBoxes = GetVisualChildCollection<TextBox>(parentGrid);
    foreach (TextBox textBox in textBoxes)
    {
        if (textBox.Tag == "Number")
        {
            // Do something..
        }
        else if (textBox.Tag == "Login")
        {
            // Do something..
        }
        else if (textBox.Tag == "Password")
        {
            // Do something..
        }
    }
}

And an implementation of GetVisualParent and GetVisualChildCollection

public static T GetVisualParent<T>(object childObject) where T : Visual
{
    DependencyObject child = childObject as DependencyObject;
    // iteratively traverse the visual tree
    while ((child != null) && !(child is T))
    {
        child = VisualTreeHelper.GetParent(child);
    }
    return child as T;
}

public static List<T> GetVisualChildCollection<T>(object parent) where T : Visual
{
    List<T> visualCollection = new List<T>();
    GetVisualChildCollection(parent as DependencyObject, visualCollection);
    return visualCollection;
}
private static void GetVisualChildCollection<T>(DependencyObject parent, List<T> visualCollection) where T : Visual
{
    int count = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < count; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(parent, i);
        if (child is T)
        {
            visualCollection.Add(child as T);
        }
        else if (child != null)
        {
            GetVisualChildCollection(child, visualCollection);
        }
    }
}