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.
What you could do is give Button a name "PART_Button". Then override OnApplyTemplate method in control. In code, you can do
var btn = this.Template.FindName("PART_Button", this) as Button;
btn.Click += ...
The event handler is searched in the class that the x:Class
directive of current file points to, which allows you adding the event handler inline without bothering to override the class and override the OnApplyTemplate
with adding handlers hassle, regardless of the place that you declare the ControlTemplate.
MainWindow.xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Button Content="asdf">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Button Content="{TemplateBinding Content}" Click="Button_Click"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Window>
MainWindow.xaml.cs:
using System.Windows;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Button clicked!");
}
}
}
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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With