none
请教关于WPF上自定义控件添加事件的问题 RRS feed

  • 问题

  • 我目前的项目创建了一个自定义控件(CustomControl),这个控件的默认模板中有一个Button,我想要在点击这个Button时触发事件,关闭当前的窗体。在UserControl中我可以使用这个Button的OnClick事件,但在CustomControl中由于没有默认的.cs文件,没办法使用原本Button的点击事件,想请教下如何为这个自定义控件模板中的Button添加事件?
    2014年4月8日 6:43

答案

  • 试了好几种方法,感觉这种不错。就展示给你了。

    首先定义CustomerControl的Template

    <Style TargetType="local:CustomControl">
          <Style.Setters>
            <Setter Property="Template">
              <Setter.Value>
                <ControlTemplate TargetType="local:CustomControl">
                  <Grid Width="100" Height="100" Background="Yellow">
                    <Button x:Name="MyButton" Width="50" Height="50" Content="Click me" IsHitTestVisible="True"></Button>
                  </Grid>
                </ControlTemplate>
              </Setter.Value>
            </Setter>
          </Style.Setters>
        </Style>

    CustomControl里包含了一个Grid,Grid里面有button,按楼主需要是需要Grid里button的click事件。

    然后就是定义CustomControl的class

    public class CustomControl : Control
        {
            public override void OnApplyTemplate()
            {
                base.OnApplyTemplate();
    
                var grid = VisualTreeHelper.GetChild(this, 0);
                var button = VisualTreeHelper.GetChild(grid, 0) as Button;
                button.Click += button_Click;
            }
    
            void button_Click(object sender, RoutedEventArgs e)
            {
                ButtonClick.BeginInvoke(null, null, null, null);
            }
    
            public event EventHandler ButtonClick;
    
        }

    这段逻辑就是首先定义一个event叫buttonclick 是为了UI使用的时候自己加handle。在apply结束template后找到相应的button子控件(可以写FINDCHILD的extension方法来更好的findchild 我这边简单按照template寻找子元素)并给其click事件加方法,在方法内触发我们定义的buttonclick事件,我这边定义为了null参数,有自己需要可以把Button和事件的参数都传上去

    下面就是在UI中使用

    <local:CustomControl x:Name="XXXXX" ButtonClick="XXXXX_ButtonClick">
    </local:CustomControl>

    后台有handle就一切搞定~!

            private void XXXXX_ButtonClick(object sender, DragEventArgs e)
            {
                    // Implement.
            }

    这样应该就搞定楼主问题了!希望采纳 选为答案~!


    • 已编辑 Leon_Chang 2014年4月8日 10:11
    • 已建议为答案 Leon_Chang 2014年4月8日 10:28
    • 已标记为答案 ZQing 2014年4月9日 7:56
    2014年4月8日 10:08
  • 嗯。是可以使用RoutedCommand的,这样好处是业务逻辑分离吧。我前面写DEMO就是用了最简单的方法吧。其实我觉得事件也不一定要执着与用Command,具体使用还是要看业务大小和框架模型的,灵活些会更好吧。感谢采纳~
    2014年4月9日 7:19

全部回复

  • 试了好几种方法,感觉这种不错。就展示给你了。

    首先定义CustomerControl的Template

    <Style TargetType="local:CustomControl">
          <Style.Setters>
            <Setter Property="Template">
              <Setter.Value>
                <ControlTemplate TargetType="local:CustomControl">
                  <Grid Width="100" Height="100" Background="Yellow">
                    <Button x:Name="MyButton" Width="50" Height="50" Content="Click me" IsHitTestVisible="True"></Button>
                  </Grid>
                </ControlTemplate>
              </Setter.Value>
            </Setter>
          </Style.Setters>
        </Style>

    CustomControl里包含了一个Grid,Grid里面有button,按楼主需要是需要Grid里button的click事件。

    然后就是定义CustomControl的class

    public class CustomControl : Control
        {
            public override void OnApplyTemplate()
            {
                base.OnApplyTemplate();
    
                var grid = VisualTreeHelper.GetChild(this, 0);
                var button = VisualTreeHelper.GetChild(grid, 0) as Button;
                button.Click += button_Click;
            }
    
            void button_Click(object sender, RoutedEventArgs e)
            {
                ButtonClick.BeginInvoke(null, null, null, null);
            }
    
            public event EventHandler ButtonClick;
    
        }

    这段逻辑就是首先定义一个event叫buttonclick 是为了UI使用的时候自己加handle。在apply结束template后找到相应的button子控件(可以写FINDCHILD的extension方法来更好的findchild 我这边简单按照template寻找子元素)并给其click事件加方法,在方法内触发我们定义的buttonclick事件,我这边定义为了null参数,有自己需要可以把Button和事件的参数都传上去

    下面就是在UI中使用

    <local:CustomControl x:Name="XXXXX" ButtonClick="XXXXX_ButtonClick">
    </local:CustomControl>

    后台有handle就一切搞定~!

            private void XXXXX_ButtonClick(object sender, DragEventArgs e)
            {
                    // Implement.
            }

    这样应该就搞定楼主问题了!希望采纳 选为答案~!


    • 已编辑 Leon_Chang 2014年4月8日 10:11
    • 已建议为答案 Leon_Chang 2014年4月8日 10:28
    • 已标记为答案 ZQing 2014年4月9日 7:56
    2014年4月8日 10:08
  • 首先非常感谢您的回答,这个办法很好。

    其次请教一下这个地方绑定事件用command是不是会更好?

    2014年4月9日 6:51
  • 嗯。是可以使用RoutedCommand的,这样好处是业务逻辑分离吧。我前面写DEMO就是用了最简单的方法吧。其实我觉得事件也不一定要执着与用Command,具体使用还是要看业务大小和框架模型的,灵活些会更好吧。感谢采纳~
    2014年4月9日 7:19
  • 恩,十分感谢您的解答。
    2014年4月9日 7:59
  • 你好,用了你的方法之后提示:无法从文本 UserFreeBackListBox_ButtonClick 创建 ButtonClick,这是为什么?
    2015年4月13日 4:23
  • 你好,加入我要在XXXXX_ButtonClick中用到自定义控件中的DataContext我该怎么做?
    2015年4月13日 4:40