|
发表于 2015-5-22 17:36:17
|
显示全部楼层
Hi,
Mick, I really thank you.
You have motivated me to get back a little to F# that I did not have much time to learn these days.
As I also try to learn WPF, mixing the two is fun.
Here's my last attempt. I tried to go a little further with WPF binding features and include some F# helpers (thanks to kaefer for this).
This time the window is run as a modal dialog, closed using DialogResult.
The Xaml
[ol]
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:ViewModel;assembly=AcadFsWpf2013"
Name="mainWindow"
Title="Draw Line"
WindowStartupLocation="CenterOwner" Height="120" Width="280" ResizeMode="NoResize">
ItemsSource="{Binding Layers}" SelectedItem="{Binding Layer}"/>
[B]
Command="{Binding OkCommand}" CommandParameter="{Binding ElementName=mainWindow}"/>
[B]
Command="{Binding CancelCommand}" CommandParameter="{Binding ElementName=mainWindow}"/>
[/ol]
Model
[ol]namespace Model
open System
open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime
type AcAp = Autodesk.AutoCAD.ApplicationServices.Application
type AcEx = Autodesk.AutoCAD.Runtime.Exception
module Helpers =
let getObject DBObject> (id : ObjectId) =
id.GetObject(OpenMode.ForRead) :?> 'a
let getObjects DBObject> : System.Collections.IEnumerable -> _ =
let rxc = RXClass.GetClass(typeof)
Seq.cast
>> Seq.choose (function
| id when id.ObjectClass.IsDerivedFrom(rxc) -> Some(getObject id)
| _ -> None)
let addEntity (ent : #Entity) (btr : BlockTableRecord) =
if not btr.IsWriteEnabled then btr.UpgradeOpen()
let id = btr.AppendEntity(ent)
btr.Database.TransactionManager.AddNewlyCreatedDBObject(ent, true)
id
type OptionBuilder() =
member b.Bind(x, f) = Option.bind f x
member b.Return(x) = Some x
member b.Zero() = None
let opt = new OptionBuilder()
let failIfNotOk (pr : #PromptResult) =
opt { if pr.Status = PromptStatus.OK then return pr }
type Editor with
member ed.GetPoint(pt, msg) =
ed.GetPoint(new PromptPointOptions(msg, BasePoint = pt, UseBasePoint = true))
open Helpers
module CadWorker =
let getLayers () =
let db = HostApplicationServices.WorkingDatabase
use tr = db.TransactionManager.StartTransaction()
db.LayerTableId
|> getObject
|> getObjects
|> Seq.map (fun l -> l.Name)
|> Seq.toArray
let drawLine (layer) =
let doc = AcAp.DocumentManager.MdiActiveDocument
let db = doc.Database
let ed = doc.Editor
let result = opt {
let! pr1 = failIfNotOk (ed.GetPoint("\nStart point: "))
let! pr2 = failIfNotOk (ed.GetPoint(pr1.Value, "\nEnd point: "))
return (pr1, pr2) }
match result with
| None -> ()
| Some (pr1, pr2) ->
use tr = db.TransactionManager.StartTransaction()
db.CurrentSpaceId
|> getObject[B]
|> addEntity (new Line(pr1.Value, pr2.Value, Layer = layer)) |> ignore
tr.Commit();[/ol]
View
[ol]namespace View
open System
open System.IO
open System.Windows
open System.Windows.Markup
open System.Xaml
open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.Runtime
type AcAp = Autodesk.AutoCAD.ApplicationServices.Application
type CommandMethods() =
[]
member x.Test () =
let win = XamlReader.Load(File.OpenRead("MainWindow.xaml")) :?> Window
AcAp.ShowModalWindow(win) |> ignore
[)>]
do ()[/ol]
ViewModel
[ol]namespace ViewModel
open System
open System.ComponentModel
open System.Windows
open System.Windows.Input
type ViewModelBase() =
let propertyChangedEvent = new DelegateEvent()
interface INotifyPropertyChanged with
[]
member x.PropertyChanged = propertyChangedEvent.Publish
member x.OnPropertyChanged propertyName =
propertyChangedEvent.Trigger([| x; new PropertyChangedEventArgs(propertyName) |])
type RelayCommand (canExecute:(obj -> bool), action:(obj -> unit)) =
let event = new DelegateEvent()
interface ICommand with
[]
member x.CanExecuteChanged = event.Publish
member x.CanExecute arg = canExecute(arg)
member x.Execute arg = action(arg)
open Model.CadWorker
type ViewModel() =
inherit ViewModelBase()
let mutable layer = "0"
let resultOk param =
(unbox param).DialogResult
drawLine(layer)
let resultCancel param =
(unbox param).DialogResult
member x.Layer
with get () = layer
and set v = layer
member x.Layers
with get () = getLayers()
member x.OkCommand =
new RelayCommand((fun _ -> true), resultOk)
member x.CancelCommand =
new RelayCommand((fun _ -> true), resultCancel)
[/ol] |
|