Как объявить обработчики событий внутри ControlTemplate? - PullRequest
6 голосов
/ 10 ноября 2010

У меня есть следующее 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>

Как мне написать AddUser_Click, чтобы получить доступ к текстовым полям Text свойства?

обн: просто чтобы прояснить ситуацию. Я знаю, как подключить обработчик событий Click здесь. Вопрос в том, как прочитать содержимое текстовых полей в нем, поскольку я не могу дать им имя, потому что они находятся в шаблоне.

Ответы [ 4 ]

20 голосов
/ 10 ноября 2010

Что вы можете сделать, это дать кнопке имя "PART_Button".Затем переопределите метод OnApplyTemplate в элементе управления.В коде вы можете сделать

var btn = this.Template.FindName("PART_Button", this) as Button;
btn.Click += ...
5 голосов
/ 10 ноября 2010

Обработчик события ищется в классе, на который указывает директива x:Class текущего файла, что позволяет добавлять встроенный обработчик события без необходимости переопределять класс и переопределять OnApplyTemplate с трудностями добавления обработчиков, независимо от места, в котором вы объявляете шаблон 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!");
    }
  }
}
1 голос
/ 10 ноября 2010

Если у вас есть доступ к шаблонному родительскому элементу (SelectedItem, FindVisualParent и т. Д.), Вы можете сделать это, если примените Names к TextBoxes.Пример, если ControlTemplate предназначен для ComboBoxItem.

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

Еще один способ получить TextBoxes в ControlTemplate - использовать визуальное дерево.Примерно так

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..
        }
    }
}

И реализация GetVisualParent и 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);
        }
    }
}
0 голосов
/ 13 августа 2017

Мне не повезло найти свой флажок, PART_CheckBox, с

 this.Template.FindName("control name", this)

метод но

 GetTemplateChild("control name")

работал.

заглушка 'ResourceDictionary'

<Style x:Key="OGrid" TargetType="{x:Type local:OrientationGrid}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:OrientationGrid}" x:Name="PART_Control">
                    <CheckBox  x:Name="PART_CheckBox"/>
                            ...

Пользовательский элемент управления, OrientationGrid, заглушка:

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        CheckBox chkbx = GetTemplateChild("PART_CheckBox") as CheckBox;
        chkbx.Checked += Chkbx_Checked;
    }

    private void Chkbx_Checked(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Event Raised");
    }
    ...

ответ основан на: WPF получает элемент из шаблона в коде

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...