Today I am going to explain how to make a calculator in WPF using F#. You will take a F# console application template than add some references, F# source files and most important the logic of coding. The steps are given below.
Step 1: First open a new project in F# (Console Application) using Visual Studio 2010 and .Net version 4.0, give a name to it. As done in the following image.
Step 2: Now add the following define references to your project by right-clicking on the project name in the Solution Explorer, as I have discussed in my previous article. You can see through the following link.
http://www.c-sharpcorner.com/UploadFile/f5b919/8674/
The references which you have to add are these:
Step 3: When you have added all these references your Solution Explorer will look like following image.
Step 4: Now Add three source files by right-clicking on your project in the Solution Explorer by selecting add new items; name them as we have given shortname.fs, operators.fs and calculator.fs.
Step 5: Now write the following code in shortname.fs file. The Shortname.fs file will contain simply type abbreviations.
namespace FSharp_XAML_demo
open System.Windows
open System.Windows.Controls
type form = Window
type txt = TextBox
type btn = Button
type ehandler = RoutedEventHandler
type eargs = RoutedEventArgs
Step 6: Now add the following code in operators.fs file. The Operators.fs file will contains simply type definitions.
module FSharp_XAML_demo.operators
open FSharp_XAML_demo
let appname = "FSharp_XAML"
let window name =
System.Windows.Application.LoadComponent(System.Uri(sprintf "/%s;component/%s" appname name, System.UriKind.Relative)) :?> form
let (?) (window : form) name =
window.FindName name
|> unbox
let inline (+=) (event : IEvent<_, _>) handler =
(event :> Microsoft.FSharp.Control.IDelegateEvent<_>).AddHandler(ehandler(handler))
Step 7: Now add the following code in Calculator.fs; this is a class which handles all computations.
namespace FSharp_XAML_demo
type Calculator(callback : string -> unit) =
let mutable value = ""
let mutable oldvalue : float option = None
let mutable op : (float -> float -> float) option = None
let mutable append = true
member private this.GetValue() =
try
float value
with _ -> 0.
member this.applyDigit d =
if append then
value <- value + d
else
append <- true
value <- d
callback value
member this.setDot() =
if append then
value <- value + "."
else
append <- true
value <- "."
callback value
member this.setOp newop =
match op, oldvalue with
| Some opV, Some oldvalueV ->
oldvalue <- Some(opV oldvalueV (this.GetValue()))
value <- ""
op <- Some newop
| _ ->
oldvalue <- Some(this.GetValue())
value <- ""
op <- Some newop
callback "0"
member this.eq() =
value <-
match op, oldvalue with
| Some opV, Some oldvalueV ->
opV oldvalueV (this.GetValue())
|> string
| _ -> value
oldvalue <- None
op <- None
append <- false
callback value
Step 8: Now right-click on your project in the Solution Explorer and select add new item and add a F# XAML template; write the following code in the xaml file. Your XAML designer will look like the following image. When you will add the xaml file then set its build property to resources.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Width="300" Height="360" Title="Calculator in WPF using F#">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="42*" />
<RowDefinition Height="68*" />
<RowDefinition Height="68*" />
<RowDefinition Height="68*" />
<RowDefinition Height="68*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBox Grid.ColumnSpan="4" Height="36" HorizontalAlignment="Left" Margin="4,4,0,0" VerticalAlignment="Top" Width="270" Name="txtResult"
IsReadOnly="True"
FontFamily="Courier New" FontSize="30" Text="0" />
<Button Content="1" FontSize="20" Grid.Row="1" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Name="num1" />
<Button Content="2" FontSize="20" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Column="1" Grid.Row="1"
Name="num2" />
<Button Content="3" FontSize="20" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Column="2" Grid.Row="1"
Name="num3" Grid.ColumnSpan="2" />
<Button Content="4" FontSize="20" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Row="2" Name="num4" />
<Button Content="5" FontSize="20" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Column="1" Grid.Row="2"
Name="num5" />
<Button Content="6" FontSize="20" Grid.Column="2" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Row="2"
Name="num6" />
<Button Content="7" FontSize="20" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Row="3" Name="num7" />
<Button Content="8" FontSize="20" Grid.Column="1" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Row="3"
Name="num8" />
<Button Content="9" FontSize="20" Grid.Column="2" Grid.ColumnSpan="2" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top"
Width="69" Grid.Row="3" Name="num9" />
<Button Content="+" FontSize="20" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Column="3" Grid.Row="1"
Name="opAdd" />
<Button Content="-" FontSize="20" Grid.Row="2" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Column="3"
Name="opSub" />
<Button Content="x" FontSize="20" Grid.Row="3" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Column="3"
Name="opMul" />
<Button Content="0" FontSize="20" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Row="4" Name="num0" />
<Button Content="." FontSize="20" Grid.Column="1" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Row="4"
Name="opDot" />
<Button Content="=" FontSize="20" Grid.Column="2" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Row="4"
Name="opEq" />
<Button Content="÷" FontSize="20" Grid.Column="3" Height="69" HorizontalAlignment="Left" VerticalAlignment="Top" Width="69" Grid.Row="4"
Name="opDiv" />
</Grid>
</Window>
Note- If you get an error in the designer (like a problem in loading the designer) then click on reload designer; it will load the designer.
Step 9: Now finally add a Xaml.fs file by right-clicking on your project in the Solution Explorer and give name to it as we have given calc.xaml.fs and write following code in the file.
namespace FSharp_XAML_demo
open System.Windows
open FSharp_XAML_demo.operators
type Calc private (xaml : form) as this =
let txtResult : txt = xaml?txtResult
let num0 : btn = xaml?num0
let num1 : btn = xaml?num1
let num2 : btn = xaml?num2
let num3 : btn = xaml?num3
let num4 : btn = xaml?num4
let num5 : btn = xaml?num5
let num6 : btn = xaml?num6
let num7 : btn = xaml?num7
let num8 : btn = xaml?num8
let num9 : btn = xaml?num9
let opAdd : btn = xaml?opAdd
let opSub : btn = xaml?opSub
let opMul : btn = xaml?opMul
let opDiv : btn = xaml?opDiv
let opDot : btn = xaml?opDot
let opEq : btn = xaml?opEq
let calc = Calculator(fun value -> txtResult.Text <- value)
do
num0.Click += this.num_Click
num1.Click += this.num_Click
num2.Click += this.num_Click
num3.Click += this.num_Click
num4.Click += this.num_Click
num5.Click += this.num_Click
num6.Click += this.num_Click
num7.Click += this.num_Click
num8.Click += this.num_Click
num9.Click += this.num_Click
opAdd.Click += this.op_Click
opSub.Click += this.op_Click
opMul.Click += this.op_Click
opDiv.Click += this.op_Click
opDot.Click += this.opDot_Click
opEq.Click += this.opEq_Click
new () =
Calc(window "Calc.xaml")
member this.num_Click (sender : obj) (_ : eargs) =
let asButton = sender :?> btn
calc.applyDigit (asButton.Content.ToString())
member this.op_Click (sender : obj) (_ : eargs) =
let asButton = sender :?> btn
match asButton.Content.ToString() with
| "+" -> calc.setOp (+)
| "-" -> calc.setOp (-)
| "x" -> calc.setOp (*)
| "÷" -> calc.setOp (/)
| _ -> ()
member this.opDot_Click (_ : obj) (_ : eargs) =
calc.setDot()
member this.opEq_Click (_ : obj) (_ : eargs) =
calc.eq()
member this.Run() =
(new Application()).Run xaml
Step 10: Your Program.fs file will remain the same like the following code.
open System
open FSharp_XAML_demo
open FSharp_XAML_demo.operators
[<EntryPoint>]
[<STAThread>]
let main _ =
Calc().Run()
Step 11: Now press F5 to run the project and your calculator is ready to use.
Output
Summary
In this article I have discussed that how to implement a calculator in WPF using F#.