F#中的自定义路由事件 [英] Custom Routed Event in F#
问题描述
我正在尝试翻译此C#代码.到目前为止,我的尝试:
I'm trying to translate this C# code. My attempt so far:
type MyButtonSimple() as self =
inherit Button()
static let TapEvent =
EventManager.RegisterRoutedEvent
( "Tap", RoutingStrategy.Bubble,
typeof<RoutedEventHandler>, typeof<MyButtonSimple>)
let tapEvent = new Event<RoutedEventHandler, RoutedEventArgs>()
let raiseTapEvent() =
let newEventArgs = new RoutedEventArgs(TapEvent)
tapEvent.Trigger(self, newEventArgs)
[<CLIEvent>]
member x.Tap = tapEvent.Publish
// For demonstration purposes we raise the event when clicked
override self.OnClick() =
raiseTapEvent()
MainWindow.xaml
MainWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:funk="clr-namespace:funk;assembly=appWPF"
Title="Routed" Height="300" Width="400">
<StackPanel Background="LightGray">
<funk:MyButtonSimple Content="Spin" Background="#808080" Foreground="LightGray">
<funk:MyButtonSimple.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="rotate"/>
</TransformGroup>
</funk:MyButtonSimple.RenderTransform>
<funk:MyButtonSimple.Triggers>
<EventTrigger RoutedEvent="funk:MyButtonSimple.Tap">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation
Storyboard.TargetName="rotate"
Storyboard.TargetProperty="Angle"
From="0" To="90" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</funk:MyButtonSimple.Triggers>
</funk:MyButtonSimple>
</StackPanel>
</Window>
单击按钮不会启动动画.
Clicking the button doesn't start the animation.
将代码RoutedEvent="funk:MyButtonSimple.Tap"
更改为RoutedEvent="GotFocus"
给出了一个有效的示例(Button.Click被覆盖).
Changing the code RoutedEvent="funk:MyButtonSimple.Tap"
to RoutedEvent="GotFocus"
gives a working example (Button.Click is overridden).
有什么想法我在做什么错吗?
Any ideas what I'm doing wrong?
推荐答案
这很棘手,因为它做了很多F#中不标准的事情.
This is tricky because it's doing quite a bit of things that aren't standard in F#.
该C#代码的翻译如下:
A translation of that C# code would be:
type MyButtonSimple() as self =
inherit Button()
static let tapEvent =
EventManager.RegisterRoutedEvent
( "Tap", RoutingStrategy.Bubble,
typeof<RoutedEventHandler>, typeof<MyButtonSimple>)
// Create a custom event so you can override AddHandler/RemoveHandler behavior
let tapEvent =
{ new IDelegateEvent<RoutedEventHandler> with
member this.AddHandler del = self.AddHandler(MyButtonSimple.TapEvent, del)
member this.RemoveHandler del = self.RemoveHandler(MyButtonSimple.TapEvent, del) }
// Raise via routed eventing strategy
let raiseTapEvent() =
let newEventArgs = new RoutedEventArgs(MyButtonSimple.TapEvent)
self.RaiseEvent newEventArgs
// This isn't exactly the same, but public static fields aren't allowed in F#, and
// this works for WPF
static member TapEvent with get() = tapEvent
[<CLIEvent>]
member x.Tap = tapEvent
// For demonstration purposes we raise the event when clicked
override self.OnClick() =
raiseTapEvent()
这里的主要陷阱"是您需要覆盖标准事件行为,这需要您自己实现IDelegateEvent
而不是使用常规的F#事件管理.另外,您无法在F#中执行公共静态只读字段,因此这会将事件包装到一个属性中.即使这不是实现路由事件的标准"方式,WPF似乎也可以.
The main "gotchas" here are that you need to override the standard event behavior, which requires implementing IDelegateEvent
yourself instead of using the normal F# event management. Also, you can't do public static readonly fields in F#, so this wraps the event into a property. WPF seems to be fine with this, even though it's not the "standard" way to implement routed events.
这篇关于F#中的自定义路由事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!