【问题标题】:F# WPF: Handling click events in ListBoxF# WPF:处理 ListBox 中的单击事件
【发布时间】:2016-12-18 18:04:22
【问题描述】:

我正在尝试使用 F# 和 WPF 创建一个简单的任务调度程序。它基本上只是一个任务列表,其中每个任务都有一个“删除”按钮。处理列表外的按钮点击不是问题——这可以使用常规命令来处理。然而,处理一个按钮点击in列表项并不简单。我尝试使用 RelayCommand 描述的 here 并将绑定路由到父级,但发送者对象始终为空(我希望它是集合中的任务对象)。还尝试按照推荐的here 附加属性,但无法使其工作。

如何分配一个事件处理程序来获取单击删除按钮的任务对象?

这是 App.fs:

namespace ToDoApp

open System
open System.Windows
open System.Collections.ObjectModel
open System.Windows.Input
open FSharp.ViewModule
open FSharp.ViewModule.Validation
open FsXaml

type App = XAML<"App.xaml">
type MainView = XAML<"MainWindow.xaml">

type Task(str) = 
    member x.Description with get() = str

type MainViewModel() as self = 
    inherit ViewModelBase()  

    let tasks = new ObservableCollection<Task>()

    let addTaskCommand() =
        let descr = sprintf "Do something at %A" (DateTime.Now.AddMinutes(30.0))
        tasks.Add <| new Task(descr)

    member this.Tasks with get() = tasks
    member this.AddTask = this.Factory.CommandSync addTaskCommand

module main =
    [<STAThread>]
    [<EntryPoint>]
    let main argv =
        App().Run()

MainWindow.xaml:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ToDoApp;assembly=ToDoApp"
    xmlns:fsxaml="http://github.com/fsprojects/FsXaml"
    Title="Simple ToDo app" Height="200" Width="400">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Name="newJobButton" Command="{Binding AddTask}" Width="100" Height="32" Margin="5, 5, 5, 5" HorizontalAlignment="Left">New task</Button>
        <ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
            <ListBox Name="lstBox" ItemsSource="{Binding Tasks}" >
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="80" />
                            </Grid.ColumnDefinitions>
                            <Label Grid.Column="0" Content="{Binding Description}" Margin="5 5 0 0"/>
                            <!-- OnClick ??? -->
                            <Button Grid.Column="1">Delete</Button>
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </ScrollViewer>
    </Grid>
</Window>

App.xaml 很简单,所以这里就不展示了。

【问题讨论】:

    标签: wpf f# fsharp.viewmodule


    【解决方案1】:

    最好坚持使用命令:

    视图模型

    member __.DelTask = 
        __.Factory.CommandSyncParam 
            (fun task -> tasks.Remove task |> ignore)
    

    XAML

    <Button Grid.Column="1" 
            Command="{Binding DataContext.DelTask, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" 
            CommandParameter="{Binding}"
            >Delete</Button>
    

    在 XAML 中使用事件处理程序会导致难以测试和维护的意大利面条式代码(即关注点分离,将业务逻辑问题与 UI 问题分开处理)。

    【讨论】:

    • 像魅力一样工作!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 1970-01-01
    • 2011-05-07
    相关资源
    最近更新 更多