【问题标题】:F# Event is being triggered multiple times . . .?F# 事件被多次触发。 . .?
【发布时间】:2013-10-27 13:25:28
【问题描述】:

我有一个非常简单的程序来从网站获取 RSS 提要并用项目填充列表框。每当用户选择一个项目并按 Enter 键时,它应该转到一个网页。这是 KeyUp 事件处理程序!

rssList.KeyUp
|> Event.filter (fun e -> rssList.SelectedItems.Count > 0)
|> Event.filter (fun (args:Input.KeyEventArgs) -> args.Key = Key.Enter)
|> Event.add  -> let feed = unbox<RSSFeed>  rssList.SelectItem)
                                            Process.Start(feed.Link) |> ignore)

我得到的是以下内容:

  • 第一次触发事件时,它工作正常,浏览器打开并加载页面
  • 第二次触发两次,所以现在我打开了两个浏览器窗口,页面都加载到了它们中。
  • 我第三次得到三个浏览器。 . .你明白了!

有人知道为什么会这样吗?我的目标是(你猜对了)只是打开 1 个浏览器窗口和 1 个页面 PER 触发器

【问题讨论】:

  • 看起来 Event.add 缺少一些代码(有趣的参数 ->)。你能解决它吗?
  • 上面的代码运行良好,我没有收到任何“缺失”代码的错误。它按预期工作。但是这里有多次执行,我不知道为什么会发生这种情况
  • @ZaidAjaj 为了诊断起见,请尝试 Eugene 的建议——将您的 Event.add -&gt; ... 更改为 Event.add (fun args -&gt; ...) 并尝试再次运行代码。编译器中总是可能存在错误,因此您没有得到解析器或输入错误。
  • @Jack 我已经尝试过了,这实际上是我的第一次尝试!然后我将事件更改为双击处理程序,然后使这两个事件由不同的处理程序处理。 . .我仍然得到相同的结果。

标签: wpf events f# f#-3.0


【解决方案1】:

您的示例中有几个编译错误,包括格式错误的 lambda 表达式、不匹配的括号、不正确的标识符(SelectItem 不是属性,我假设您的意思是 SelectedItem 不是 SelectedItems),以及后面的缩进不正确let feed 绑定。

下面是一个简化的示例,可以按您的预期工作。当用户按 Enter 键时,顶部 ListBox 中的选定项被放入底部 ListBox。

open System
open System.Windows
open System.Windows.Controls
open System.Windows.Input

[<EntryPoint>]
[<STAThread>]
let main argv = 
    let panel = new DockPanel()
    let listBox = new ListBox()
    for i in [| 1 .. 10 |] do
        listBox.Items.Add i |> ignore
    DockPanel.SetDock(listBox, Dock.Top)
    let listBox2 = new ListBox(Height = Double.NaN)
    panel.Children.Add listBox |> ignore
    panel.Children.Add listBox2 |> ignore
    listBox.KeyUp
        |> Event.filter (fun e -> listBox.SelectedItems.Count > 0)
        |> Event.filter (fun e -> e.Key = Key.Enter)
        |> Event.add (fun e ->  let i = unbox<int> listBox.SelectedItem
                                listBox2.Items.Add(i) |> ignore)
    let win = new Window(Content = panel)
    let application = new Application()
    application.Run(win) |> ignore
    0

【讨论】:

  • 我复制粘贴了该代码并在帖子页面上使用它,但是,问题不在于填充列表框,我已经成功地管理它,但问题是事件触发了它一次又一次的自我
  • 我尝试了几件事,我意识到我可以实现 MouseButtonEventArgs.Handled 属性来防止事件重新触发自身
  • @ZaidAjaj 听起来正在发生的事情是您将多个处理程序附加到KeyUp 事件。 (也许您正在将处理程序添加到另一个经常触发的事件处理程序中?)注册一次KeyUp 事件。
  • 我实际上是这样做的,并且查看运行时,它每次触发都会触发 1 次,所以第四次有人打开页面时,他得到 4 个页面,我什至为它但也没有用!然后最后,我实现了事件参数的 Handled 属性并且它起作用了! (见下文):)
【解决方案2】:

我通过使用以下内容实现事件参数的 Handled 属性使其正常工作:

let doubleClick = new MouseButtonEventHandler(fun sender (args:MouseButtonEventArgs) ->
    let listBox = unbox<ListBox> sender
    match listBox.SelectedItems.Count > 0 with
    | true -> 
        let listBox = unbox<ListBox> sender
        let feed = unbox<RSSFeed> listBox.SelectedItem
        Process.Start(feed.Link) |> ignore
        args.Handled <- true; ()
    | false -> 
        args.Handled <- true; ())

感谢所有在这里帮助过我的人!

【讨论】:

    猜你喜欢
    • 2013-07-06
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    相关资源
    最近更新 更多