2016-12-18 2 views
4

Я пытаюсь создать простой планировщик задач с использованием F # и WPF. Это просто список задач, в которых каждая задача имеет кнопку «Удалить». Обработка щелчков кнопок за пределами списка не является проблемой - это может быть выполнено с помощью обычной команды. Однако обращение к кнопке в Элемент списка не прост. Я попытался использовать RelayCommand описал here с привязкой, направленной к родительскому, но объект-отправитель всегда равен нулю (я ожидал, что это объект задачи из коллекции). Также попытался добавить свойство, как рекомендовано here, но не смог заставить его работать.F # WPF: Обработка событий щелчка в ListBox

Как назначить обработчик события, который получает объект задачи с нажатой кнопкой «Удалить»?

Вот в 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 тривиально, поэтому я не показывая его здесь.

ответ

4

Это лучше придерживаться команд:

ViewModel

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 в запутанного кода, который тверже, чтобы проверить и поддерживать (то есть разделение проблем, обработку проблем бизнес-логики s отдельно от проблем пользовательского интерфейса).

+1

Работает как очарование! Спасибо! –

Смежные вопросы