open System.ComponentModel open Microsoft.FSharp.Quotations.Patterns type ObservableObject () = let propertyChanged = Event<PropertyChangedEventHandler,PropertyChangedEventArgs>() let getPropertyName = function | PropertyGet(_,pi,_) -> pi.Name | _ -> invalidOp "Expecting property getter expression" interface INotifyPropertyChanged with [<CLIEvent>] member this.PropertyChanged = propertyChanged.Publish member this.NotifyPropertyChanged propertyName = propertyChanged.Trigger(this,PropertyChangedEventArgs(propertyName)) member this.NotifyPropertyChanged quotation = quotation |> getPropertyName |> this.NotifyPropertyChanged type MessageViewModel () = inherit ObservableObject() let mutable text = "" member this.Message with get () = text and set value = text <- value this.NotifyPropertyChanged <@ this.Message @> open System.Windows open System.Windows.Controls open System.Windows.Markup let xaml = @"<UserControl xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'> <TextBlock FontSize='48' Text='{Binding Message}'/> </UserControl>" #if INTERACTIVE open Microsoft.TryFSharp App.Dispatch (fun() -> App.Console.ClearCanvas() let view = XamlReader.Load(xaml) :?> UserControl let viewModel = MessageViewModel(Message="Countdown") view.DataContext <- viewModel view |> App.Console.Canvas.Children.Add async { do! Async.Sleep(2000) for i = 10 downto 1 do viewModel.Message <- i.ToString() do! Async.Sleep(1000) viewModel.Message <- "Blast off!" } |> Async.StartImmediate App.Console.CanvasPosition <- CanvasPosition.Right ) #endif