G.Y*_*G.Y 12 .net c# wpf custom-controls wpf-controls
WPF自定义控件
我想构建一个新的自定义控件.我发现很少的教程给了我一些如何实现这一目标的线索.据我了解,创建一个新的自定义控件总是通过扩展当前控件来完成,甚至可以从层次结构的最基本级别扩展控件,例如,您甚至可以扩展:
如以下教程中所述: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>
Run Code Online (Sandbox Code Playgroud)假设我在我的ControlTemplate中有一个带有fill属性的元素,名为x:name ="LeftTraingularIndicator"
问题:
现在我想在我的XAML中对IsMouseDown做出反应.我怎么做?没有"IsMouseDown"触发器.此外,如果我想对后面的代码做出反应,该怎么办?如果我想从后面的代码中更改LeftTraingularIndicator"Fill",还有什么呢?
我现在正在尝试2天......感觉我在理解事情如何运作时遗漏了一些东西.没有找到任何深入解释这些问题的教程.
我希望看到我在这里提出的每个问题的几行例子.
谢谢.
G.Y*_*G.Y 10
经过广泛研究......
1)将事件暴露给外部......就像你从任何其他阶级暴露出来一样.
public delegate void myDelegate(int someValue);
public event myDelegate myEvent;
Run Code Online (Sandbox Code Playgroud)
在你的代码中的某个地方:
if(myEvent!=null)
myEvent(5);
Run Code Online (Sandbox Code Playgroud)
那部分没什么新东西.
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.
}
Run Code Online (Sandbox Code Playgroud)
3)不推荐 - 因为它属于用户控件的范围而不是自定义控件.自定义控件是"原子",用户控件更适合组合控件的目的.
但并非不可能......
var myButton = (Button)Template.FindName("myButton",this);
myButton.OnMouseMove += ....
Run Code Online (Sandbox Code Playgroud)
请记住:
必须在代码隐藏中找到任何应该知道的内容.
你的xaml应该不知道背后的代码是做什么的.(除了! - 继续阅读)
在设计XAML时,代码隐藏中应该知道的部件必须具有正确的名称.
我真的希望这会帮助那些在尝试开发自己的自定义控件时获得"墙"的人.
小智 7
如果我理解你的问题 - 以下是我的解释.
WPF事件系统提供3种类型的事件:1.冒泡2.隧道3.直接
如果事件(在内部)被定义为冒泡事件,则事件将从源传递到其容器.例如:如果Grid有两个按钮 - Rectangle1和Rectangle2,那么对这些矩形的任何点击都会向上冒泡到Grid.隧道是相反的,事件从父母隧道到孩子.
直接活动非常特别 - 它们仅适用于没有意义的活动.例如,在上面的场景中,在任一个矩形上冒泡MouseOver事件都没有意义 - 因为每次鼠标进入矩形时,事件都会冒泡到网格 - 这是人们可能期望的.
你的问题:
可以使用我的控件的窗口(或容器)可以使用的事件:那些是我想要暴露给外部的事件..如何编写这些事件?
你基本上需要写一个冒泡事件.下面是一个msdn的示例,用于在Button上写一个冒泡的tap事件(我自己没有尝试过)路由事件示例:
public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
"Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));
Run Code Online (Sandbox Code Playgroud)
你的问题:
问题:现在我想在我的XAML中对IsMouseDown做出反应......我该怎么做?没有"IsMouseDown"触发器......如果我想对后面的代码做出反应,还有什么呢?如果我想从后面的代码中更改LeftTraingularIndicator"Fill",还有什么呢?
顺便说一下,你似乎对事件和触发器有些混淆(因为我看到你可以互换使用它们).虽然它们是相关的,但它们并不相同.
回到你的问题 - WPF允许触发属性更改 - 这实际上就是你要挂钩的 - 在这种情况下是IsMouseOver.但缺少的是该属性是ControlTemplate的目标(我不知道它是什么).我只是推断ControlTemplate的目标是一个Rectangle.在这种情况下,它没有"IsMouseDown"属性来挂钩属性触发器.这就是你无法找到它的原因.另一个选项你必须写一个AttachedEvent(它们与AttachedProperties非常相似)..另一个话题:(
我希望我尽我所能:)