首页 文章

WPF自定义控件构造,触发器和事件

提问于
浏览
12

WPF自定义控件

我想构建一个新的自定义控件 . 我发现很少的教程给了我一些如何实现这一目标的线索 . 据我了解,创建一个新的自定义控件总是通过扩展当前控件来完成,甚至可以从层次结构的最基本级别扩展控件,例如,您甚至可以扩展:

  • UIElement

  • FrameworkElement

  • 控制

  • ContentControl

  • HeaderedContentControl

  • ItemsControl

  • 选择器

  • RangeBase

如以下教程中所述:http://wpftutorial.net/HowToCreateACustomControl.html

所以,我按照教程创建了一个自定义控件库类型的新项目,得到了我的通用.xaml和我的代码 . 到现在为止还挺好 .

我可以区分3种类型或类别的事件 .

  • 将使用我的控件的窗口(或容器)可以使用的事件:那些是我想要暴露给外部的事件 . 怎么写那些?

  • 与控件本身相关且不在外部暴露的事件;例如,如果鼠标超出我的控制范围,我想对此做出反应 . 我可以在XAML中做到这一点:

<ControlTemplate.Triggers>
  <Trigger Property="IsMouseOver" Value="true">  
    <Setter Property="Fill" TargetName="LeftTraingularIndicator">  
      <Setter.Value>  
        <SolidColorBrush Color="Yellow" />  
      </Setter.Value>  
    </Setter>
  </Trigger>
</ControlTemplate.Triggers>

假设我在我的ControlTemplate中有一个带有fill属性的元素,名为x:name =“LeftTraingularIndicator”

问题:

现在我想在我的XAML中对IsMouseDown做出反应 . 我怎么做?没有“IsMouseDown”触发器 . 此外,如果我想对后面的代码做出反应,该怎么办?如果我想从后面的代码中更改LeftTraingularIndicator“Fill”,还有什么呢?

  • 与子元素相关的事件,这些子元素是我的ControlTemplate的可视化构造的一部分,例如,如果我想对XAML中的"LeftTraigularIndicator"的"LeftTraigularIndicator"做出反应,甚至是在Code Behind中?也许两者都有 .

我现在正在尝试2天......感觉我在理解事情如何运作时遗漏了一些东西 . 没有找到任何深入解释这些问题的教程 .

我希望看到我在这里提出的每个问题的几行例子 .

谢谢 .

2 回答

  • 7

    经过广泛研究......

    1)将事件暴露给外部......就像你从任何其他阶级暴露出来一样 .

    public delegate void myDelegate(int someValue);  
    public event myDelegate myEvent;
    

    在你的代码中的某个地方:

    if(myEvent!=null)
      myEvent(5);
    

    那部分没什么新东西 .

    2)从后面的代码创建一个实例构造函数

    public MyCustomControl()
    {
        MouseMove += MyCustomControl_MouseMove;
    }
    
    
    void MyCustomControl_MouseMove(object sender, MouseEventArgs e)
    {
       //now you can react to the movement of the mouse.
       //if for example I want to address an element, let's say a rectangle:
    
       var ele = (Rectangle)Template.FindName("myRect",this);
       ele.Fill=myNewBrush;
    
       // provided that we have an element named "myRect" (x:name="myRect") in
       // the generic.xaml style->Control Template-> which corresponds to that name.
    
    }
    

    3)不推荐 - 因为它属于用户控件的范围而不是自定义控件 . 自定义控件是“原子”,用户控件更适合组合控件的目的 .

    但并非不可能......

    var myButton = (Button)Template.FindName("myButton",this);
    myButton.OnMouseMove += ....
    

    请记住:

    • 必须在代码隐藏中找到任何应该知道的内容 .

    • 你的xaml应该不知道背后的代码是做什么的 . (除了! - 继续阅读)

    • 在设计XAML时,代码隐藏中应该知道的部件必须具有正确的名称 .

    我真的希望这会帮助那些在尝试开发自己的自定义控件时获得“墙”的人 .

  • 9

    如果我理解你的问题 - 以下是我的解释 .

    WPF事件系统提供3种类型的事件:1 . 冒泡2.隧道3.直接

    如果事件(在内部)被定义为冒泡事件,则事件将从源传递到其容器 . 例如:如果Grid有两个按钮 - Rectangle1和Rectangle2,那么对这些矩形的任何点击都会向上冒泡到Grid . 隧道是相反的,事件从父母隧道到孩子 .

    直接活动非常特别 - 它们仅适用于没有意义的活动 . 例如,在上面的场景中,在任一个矩形上冒泡MouseOver事件都没有意义 - 因为每次鼠标进入矩形时,事件都会冒泡到网格 - 这是人们可能期望的 .

    你的问题:

    可以使用我的控件的窗口(或容器)可以使用的事件:那些是我想要暴露给外部的事件..如何编写这些事件?

    你基本上需要写一个冒泡事件 . 下面是一个msdn的例子,用于在Button上写一个冒泡的tap事件(我自己没试过)Routed event example

    public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
    "Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));
    

    你的问题:

    问题:现在我想在我的XAML中对IsMouseDown做出反应......我该怎么做?没有“IsMouseDown”触发器......如果我想对后面的代码做出反应,还有什么呢?如果我想从代码中更改LeftTraingularIndicator“Fill”,甚至更进一步背后?

    顺便说一下,你似乎对事件和触发器有些混淆(因为我看到你可以互换使用它们) . 虽然它们是相关的,但它们并不相同 .

    回到你的问题 - WPF允许触发属性更改 - 这实际上就是你要挂钩的 - 在这种情况下是IsMouseOver . 但缺少的是该属性是ControlTemplate的目标(我不知道它是什么) . 我只是推断ControlTemplate的目标是一个Rectangle . 在这种情况下,它没有“IsMouseDown”属性来挂钩属性触发器 . 这就是你无法找到它的原因 . 另一个选项你必须写一个AttachedEvent(它们与AttachedProperties非常相似)..另一个话题:(

    我希望我尽我所能:)

相关问题