I built a calculator in C# with WPF for the UI. I'm still a beginner at WPF and C# in general, and I'm just looking for some constructive criticism.
XAML
<Window x:Class="Calculator.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Calculator"
mc:Ignorable="d"
Title="Calculator" Height="350" Width="525">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="1"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="FontFamily" Value="Consolas"/>
</Style>
</Window.Resources>
<DockPanel>
<TextBox DockPanel.Dock="Top" x:Name="currentEquation" Height="50" IsEnabled="False" FontSize="30" VerticalContentAlignment="Center" FontFamily="Consolas" Foreground="Black">
</TextBox>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button x:Name="b1" Grid.Column="0" Content="1"/>
<Button x:Name="b2" Grid.Column="1" Content="2"/>
<Button x:Name="b3" Grid.Column="2" Content="3"/>
<Button x:Name="bdelete" Grid.Column="3" Content="Del"/>
<Button x:Name="bclear" Grid.Column="4" Content="Clear"/>
<Button x:Name="b4" Grid.Column="0" Grid.Row="1" Content="4"/>
<Button x:Name="b5" Grid.Column="1" Grid.Row="1" Content="5"/>
<Button x:Name="b6" Grid.Column="2" Grid.Row="1" Content="6"/>
<Button x:Name="bplus" Grid.Column="3" Grid.Row="1" Content="+"/>
<Button x:Name="bminus" Grid.Column="4" Grid.Row="1" Content="-"/>
<Button x:Name="b7" Grid.Column="0" Grid.Row="2" Content="7"/>
<Button x:Name="b8" Grid.Column="1" Grid.Row="2" Content="8"/>
<Button x:Name="b9" Grid.Column="2" Grid.Row="2" Content="9"/>
<Button x:Name="btimes" Grid.Column="3" Grid.Row="2" Content="×"/>
<Button x:Name="bdivide" Grid.Column="4" Grid.Row="2" Content="÷"/>
<Button x:Name="b0" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" Content="0"/>
<Button x:Name="bdot" Grid.Column="2" Grid.Row="3" Content="."/>
<Button x:Name="bequals" Grid.Column="3" Grid.ColumnSpan="2" Grid.Row="3" Content="="/>
</Grid>
</DockPanel>
</Window>
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace Calculator
{
public partial class MainWindow: Window
{
Calculator c;
public MainWindow()
{
InitializeComponent();
this.Loaded += OnLoad;
}
void OnLoad(object sender, RoutedEventArgs e)
{
c = new Calculator(currentEquation);
AddClickEvents();
}
void AddClickEvents()
{
b1.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(1);
};
b2.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(2);
};
b3.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(3);
};
b4.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(4);
};
b5.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(5);
};
b6.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(6);
};
b7.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(7);
};
b8.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(8);
};
b9.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(9);
};
b0.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(0);
};
bdot.Click += (object sender, RoutedEventArgs e) =>
{
c.Press('.');
};
bplus.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(Calculator.Function.Add);
};
bminus.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(Calculator.Function.Minus);
};
btimes.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(Calculator.Function.Times);
};
bdivide.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(Calculator.Function.Divide);
};
bequals.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(Calculator.Function.Equals);
};
bdelete.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(Calculator.Function.Delete);
};
bclear.Click += (object sender, RoutedEventArgs e) =>
{
c.Press(Calculator.Function.Clear);
};
}
private class Calculator
{
TextBox tb;
private static class States
{
public static bool hasDot;
public static bool willReplace;
public static Function currentFunction;
public static Dictionary<float, Function> lastNumberAndFunction;
}
public enum Function
{
Add,
Minus,
Times,
Divide,
Equals,
Delete,
Clear,
None
}
public Calculator(TextBox text)
{
tb = text;
States.hasDot = false;
States.willReplace = false;
States.currentFunction = Function.None;
States.lastNumberAndFunction = new Dictionary<float, Function>();
}
public void Press(int number)
{
if(States.willReplace)
{
tb.Text = number.ToString();
States.willReplace = false;
return;
};
tb.Text += number;
}
public void Press(char c)
{
if(c == '.' && !States.hasDot)
{
tb.Text += c;
States.hasDot = true;
}
}
public void Press(Function fn)
{
switch(fn)
{
case Function.Add:
case Function.Minus:
case Function.Times:
case Function.Divide:
States.lastNumberAndFunction.Add(float.Parse(tb.Text), States.currentFunction);
States.currentFunction = fn;
States.willReplace = true;
break;
case Function.Equals:
States.lastNumberAndFunction.Add(float.Parse(tb.Text), States.currentFunction);
Equals();
break;
case Function.Delete:
tb.Text = String.Join("", tb.Text.Reverse().Skip(1).Reverse());
if(!tb.Text.Contains(".")) States.hasDot = false;
break;
case Function.Clear:
tb.Text = "";
States.hasDot = false;
break;
}
}
void Equals()
{
float final = 0;
foreach(KeyValuePair<float, Function> numberAndFunction in States.lastNumberAndFunction)
{
switch(numberAndFunction.Value)
{
case Function.None:
final = numberAndFunction.Key;
break;
case Function.Add:
final += numberAndFunction.Key;
break;
case Function.Minus:
final -= numberAndFunction.Key;
break;
case Function.Times:
final *= numberAndFunction.Key;
break;
case Function.Divide:
if(numberAndFunction.Key == 0)
{
final = 0;
break;
}
final /= numberAndFunction.Key;
break;
}
}
tb.Text = final.ToString();
States.lastNumberAndFunction.Clear();
States.hasDot = false;
States.currentFunction = Function.None;
States.willReplace = true;
}
}
}
}
enum
that includes aNone
value, I'd recommend thatNone
is the first value. \$\endgroup\$