【问题标题】:assign click event to a Button in a DataTemplate将点击事件分配给 DataTemplate 中的按钮
【发布时间】:2019-12-06 18:18:07
【问题描述】:
<Window x:Class="WpfApp12.MainWindow"
    xmlns=...usual namespaces...
    Loaded="Window_Loaded"
    >

<Window.Resources>

    <DataTemplate x:Key="myHeaderTemplate">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{TemplateBinding Content}"/>
            <Button Margin="5,0,0,0" x:Name="MyButton">Press me</Button>
        </StackPanel>
    </DataTemplate>

</Window.Resources>

<!-- Just point the datacontext to the code behind -->
<Window.DataContext>
    <Binding RelativeSource="{RelativeSource Mode=Self}"/>
</Window.DataContext>

<DataGrid Name="DG" ItemsSource="{Binding People}"/>

</Window>

这与下面的代码一起给出了我想要的:一个 DataGrid 的列,其标题已被动态分配一个 DataTemplate 和一个按钮“按我”:

背后的代码:

public partial class MainWindow : Window
{

    public class Person
    {
        public string Name { get; set; }
        public string Surname { get; set; }
    }

    public MainWindow()
    {
        People.Add(new Person() { Name = "Isaac", Surname = "Newton" });
        People.Add(new Person() { Name = "Galileo", Surname = "Galilei" });

        InitializeComponent();
    }

    public ObservableCollection<Person> People { get; } = new ObservableCollection<Person>();

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        DG.Columns[0].HeaderTemplate = (DataTemplate)FindResource("myHeaderTemplate");
        //how to access the button in the template in order to assign the click event?
    }

    private void MyButton_Click(object sender, RoutedEventArgs e)
    {
        //DO SOMETHING
    }

  }
}

现在我想将MyButton_Click 事件动态连接到模板中的按钮。

这类问题似乎有很多覆盖面,这是最好的问题之一: WPF How to access control from DataTemplate 有类似的东西:

ComboBox myCombo =  _contentPresenter.ContentTemplate.FindName("myCombo", _contentPresenter) as ComboBox;

我对模板不是很熟悉,也找不到起点,即调用 FindName 的“内容呈现器”。

【问题讨论】:

  • 说实话,这个实现对我来说看起来很奇怪,根本不适合 WPF 的 MVVM 方法......
  • 实际上,除了在标题中添加一个按钮之外几乎没有什么;代码在代码隐藏中只是为了保持简单。问题是如何连接按钮,你知道吗?

标签: c# wpf


【解决方案1】:

您可以使用递归辅助方法在可视化树中找到Button:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    DG.Columns[0].HeaderTemplate = (DataTemplate)FindResource("myHeaderTemplate");
    DG.Dispatcher.BeginInvoke(new Action(() =>
    {
        DataGridColumnHeadersPresenter presenter = FindVisualChild<DataGridColumnHeadersPresenter>(DG);
        DataGridCellsPanel dataGridCellsPanel = FindVisualChild<DataGridCellsPanel>(presenter);
        DataGridColumnHeader header = dataGridCellsPanel.Children[0] as DataGridColumnHeader;
        Button button = FindVisualChild<Button>(header);
        if (button != null)
            button.Click += MyButton_Click;
    }));
}

private void MyButton_Click(object sender, RoutedEventArgs e)
{
    //DO SOMETHING
}

private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child != null && child is T)
            return (T)child;
        else
        {
            T childOfChild = FindVisualChild<T>(child);
            if (childOfChild != null)
                return childOfChild;
        }
    }
    return null;
}

【讨论】:

  • @AgostinoX:你试过这个吗?
猜你喜欢
  • 1970-01-01
  • 2014-03-29
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多