WPF实现简易计算器(MVVM、控件自定义样式)

 

 

WPF实现简易计算器(MVVM、控件自定义样式)

运行环境:VS2022 .Net framework4.8
完整项目:Gitee仓库

界面#

界面如下图所示

界面图片

文件结构#

文件结构:
MVVM实现: Calculator_Model、Calculator_ViewModel、RelayCommond、MainWindow
控件自定义样式:CustomButton、CustomButtonStyle

详细如下图所示

项目结构图

项目代码#

MainWindow.xaml

<Window x:Class="MyCalculator.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:MyCalculator"
        mc:Ignorable="d"
        Title="我的计算器" Height="400" Width="300" MinHeight="400" MinWidth="300">
    <Grid Background="#f9f9f9">
        <Grid.RowDefinitions>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="8*"/>
        </Grid.RowDefinitions>

        <Grid Grid.Row="0">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="2*"/>
            </Grid.RowDefinitions>
            <TextBox Grid.Row="0" Text="{Binding Str1}" HorizontalAlignment="Right" FontSize="15" Foreground="#616161" BorderBrush="{x:Null}" BorderThickness="0" Background="#f9f9f9"/>
            <TextBox Grid.Row="1" Text="{Binding Str2}" HorizontalAlignment="Right" FontSize="30" Foreground="Black" BorderBrush="{x:Null}" BorderThickness="0" Background="#f9f9f9"/>
        </Grid>

        <Grid Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <local:CustomButton Grid.Row="0" Grid.Column="0" Content="x²" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#b2dbff" BackgroundHover="#c5e4ff" BackgroundPress="#d9edff" Command="{Binding Powx}"/>
            <local:CustomButton Grid.Row="0" Grid.Column="1" Content="√x" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#b2dbff" BackgroundHover="#c5e4ff" BackgroundPress="#d9edff" Command="{Binding Sqrtx}"/>
            <local:CustomButton Grid.Row="0" Grid.Column="2" Content="C" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#b2dbff" BackgroundHover="#c5e4ff" BackgroundPress="#d9edff" Command="{Binding Clear}"/>
            <local:CustomButton Grid.Row="0" Grid.Column="3" Content="⌫" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#b2dbff" BackgroundHover="#c5e4ff" BackgroundPress="#d9edff" Command="{Binding Backspace}"/>
            <local:CustomButton Grid.Row="1" Grid.Column="0" Content="7" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum7}"/>
            <local:CustomButton Grid.Row="1" Grid.Column="1" Content="8" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum8}"/>
            <local:CustomButton Grid.Row="1" Grid.Column="2" Content="9" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum9}"/>
            <local:CustomButton Grid.Row="1" Grid.Column="3" Content="÷" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#b2dbff" BackgroundHover="#c5e4ff" BackgroundPress="#d9edff" Command="{Binding Div}"/>
            <local:CustomButton Grid.Row="2" Grid.Column="0" Content="4" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum4}"/>
            <local:CustomButton Grid.Row="2" Grid.Column="1" Content="5" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum5}"/>
            <local:CustomButton Grid.Row="2" Grid.Column="2" Content="6" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum6}"/>
            <local:CustomButton Grid.Row="2" Grid.Column="3" Content="×" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#b2dbff" BackgroundHover="#c5e4ff" BackgroundPress="#d9edff" Command="{Binding Mul}"/>
            <local:CustomButton Grid.Row="3" Grid.Column="0" Content="1" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum1}"/>
            <local:CustomButton Grid.Row="3" Grid.Column="1" Content="2" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum2}"/>
            <local:CustomButton Grid.Row="3" Grid.Column="2" Content="3" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum3}"/>
            <local:CustomButton Grid.Row="3" Grid.Column="3" Content="-" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#b2dbff" BackgroundHover="#c5e4ff" BackgroundPress="#d9edff" Command="{Binding Sub}"/>
            <local:CustomButton Grid.Row="4" Grid.Column="0" Content="0" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding Addnum0}"/>
            <local:CustomButton Grid.Row="4" Grid.Column="1" Content="." Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#cccccc" BackgroundHover="#dddddd" BackgroundPress="#eeeeee" Command="{Binding AddDot}"/>
            <local:CustomButton Grid.Row="4" Grid.Column="2" Content="=" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#b2dbff" BackgroundHover="#c5e4ff" BackgroundPress="#d9edff" Command="{Binding Equ}"/>
            <local:CustomButton Grid.Row="4" Grid.Column="3" Content="+" Margin="2" FontSize="30" ButtonCornerRadius="10" Background="#b2dbff" BackgroundHover="#c5e4ff" BackgroundPress="#d9edff" Command="{Binding Plus}"/>

        </Grid>
    </Grid>
</Window>

Calculator_ViewModel.cs

using System;
using System.ComponentModel;
using System.Windows.Input;

namespace MyCalculator
{
    internal class Calculator_ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        //Model实例化
        private Calculator_Model _CalculatorM = new Calculator_Model();

        #region 声明数据
        /// <summary>
        /// 声明Model的数据
        /// </summary>
        public double Num1
        {
            get { return _CalculatorM.Num1; }
            set
            {
                _CalculatorM.Num1 = value;
                RaisePropertyChanged("Num1");
            }
        }

        public double Num2
        {
            get { return _CalculatorM.Num2; }
            set
            {
                _CalculatorM.Num2 = value;
                RaisePropertyChanged("Num2");
            }
        }

        public string Flag1
        {
            get { return _CalculatorM.Flag1; }
            set
            {
                _CalculatorM.Flag1 = value;
                RaisePropertyChanged("Flag1");
            }
        }

        public string Flag2
        {
            get { return _CalculatorM.Flag2; }
            set
            {
                _CalculatorM.Flag2 = value;
                RaisePropertyChanged("Flag2");
            }
        }

        public string Str1
        {
            get { return _CalculatorM.Str1; }
            set
            {
                _CalculatorM.Str1 = value;
                RaisePropertyChanged("Str1");
            }
        }

        public string Str2
        {
            get { return _CalculatorM.Str2; }
            set
            {
                _CalculatorM.Str2 = value;
                RaisePropertyChanged("Str2");
            }
        }
        #endregion



        /// <summary>
        /// 按钮控件函数
        /// </summary>
        void Btn_Addnum0()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "0";
            }
            else
            {
                Str2 = Str2 + "0";
            }
        }

        void Btn_Addnum1()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "1";
            }
            else
            {
                Str2 = Str2 + "1";
            }
        }

        void Btn_Addnum2()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "2";
            }
            else
            {
                Str2 = Str2 + "2";
            }
        }

        void Btn_Addnum3()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "3";
            }
            else
            {
                Str2 = Str2 + "3";
            }
        }

        void Btn_Addnum4()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "4";
            }
            else
            {
                Str2 = Str2 + "4";
            }
        }

        void Btn_Addnum5()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "5";
            }
            else
            {
                Str2 = Str2 + "5";
            }
        }

        void Btn_Addnum6()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "6";
            }
            else
            {
                Str2 = Str2 + "6";
            }
        }

        void Btn_Addnum7()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "7";
            }
            else
            {
                Str2 = Str2 + "7";
            }
        }

        void Btn_Addnum8()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "8";
            }
            else
            {
                Str2 = Str2 + "8";
            }
        }

        void Btn_Addnum9()
        {
            if (Str1 != null && Str1.Contains("="))
            {
                Str1 = null;
                Str2 = "9";
            }
            else
            {
                Str2 = Str2 + "9";
            }
        }

        void Btn_AddDot()
        {
            if (Str2 == null)
            {
                return;
            }
            else if (!Str2.Contains("."))
            {
                Str2 = Str2 + ".";
            }
        }

        void Btn_Powx()
        {
            Flag2 = "pow";
            if (Str2 != null && Str1 == null)
            {
                Str1 = $"pow({Str2})=";
                Num1 = double.Parse(Str2);
                Str2 = Math.Pow(Num1, 2).ToString();
            }
            else if (Str2 != null && (!Str1.Contains(Flag2)))
            {
                Str1 = $"pow({Str2})=";
                Num1 = double.Parse(Str2);
                Str2 = Math.Pow(Num1, 2).ToString();
            }
        }

        void Btn_Sqrtx()
        {
            Flag2 = "sqrt";
            if (Str2 != null && Str1 == null)
            {
                Str1 = $"sqrt({Str2})=";
                Num1 = double.Parse(Str2);
                Str2 = Math.Pow(Num1, 0.5).ToString();
            }
            else if (Str2 != null && (!Str1.Contains(Flag2)))
            {
                Str1 = $"sqrt({Str2})=";
                Num1 = double.Parse(Str2);
                Str2 = Math.Pow(Num1, 0.5).ToString();
            }
        }

        void Btn_Clear()
        {
            Num1 = 0;
            Num2 = 0;
            Str1 = null;
            Str2 = null;
            Flag1 = null;
            Flag2 = null;
        }

        void Btn_Backspace()
        {
            if (Str2 != null && Str2.Length > 1)
            {
                Str2 = Str2.Substring(0, Str2.Length - 1);
            }
            else
            {
                Str2 = null;
            }
        }

        void Btn_Plus()
        {
            Flag1 = "+";
            if ((Str1 == null && Str2 != null) || Str1.Contains("="))
            {
                Str1 = Str2 + "+";
                Str2 = null;
            }
            else if (Str1.Contains("-") || Str1.Contains("×") || Str1.Contains("÷"))
            {
                Str1 = Str1.Substring(0, Str1.Length - 1);
                Str1 = Str1 + "+";
            }
        }

        void Btn_Sub()
        {
            Flag1 = "-";
            if ((Str1 == null && Str2 != null) || Str1.Contains("="))
            {
                Str1 = Str2 + "-";
                Str2 = null;
            }
            else if (Str1.Contains("+") || Str1.Contains("×") || Str1.Contains("÷"))
            {
                Str1 = Str1.Substring(0, Str1.Length - 1);
                Str1 = Str1 + "-";
            }
        }

        void Btn_Mul()
        {
            Flag1 = "×";
            if ((Str1 == null && Str2 != null) || Str1.Contains("="))
            {
                Str1 = Str2 + "×";
                Str2 = null;
            }
            else if (Str1.Contains("+") || Str1.Contains("-") || Str1.Contains("÷"))
            {
                Str1 = Str1.Substring(0, Str1.Length - 1);
                Str1 = Str1 + "×";
            }
        }

        void Btn_Div()
        {
            Flag1 = "÷";
            if ((Str1 == null && Str2 != null) || Str1.Contains("="))
            {
                Str1 = Str2 + "÷";
                Str2 = null;
            }
            else if (Str1.Contains("+") || Str1.Contains("-") || Str1.Contains("×"))
            {
                Str1 = Str1.Substring(0, Str1.Length - 1);
                Str1 = Str1 + "÷";
            }
        }

        void Btn_Equ()
        {
            if (Str1!=null&&Str2!=null&&(!Str1.Contains("=")))
            {
                if(Str1.Contains("+") || Str1.Contains("-") || Str1.Contains("×") || Str1.Contains("÷"))
                {
                    double ans;
                    Num1 = double.Parse(Str1.Substring(0, Str1.Length - 1));
                    Num2 = double.Parse(Str2);
                    switch (Str1.Substring(Str1.Length - 1, 1))
                    {
                        case "+": ans = Num1 + Num2;break;
                        case "-": ans = Num1 - Num2; break;
                        case "×": ans = Num1 * Num2; break;
                        case "÷": ans = Num1 / Num2; break;
                        default: return;
                    }
                    Str1 = Str1 + Str2 + "=";
                    Str2=ans.ToString();
                }
            }
        }

        bool CanLoginExecute()
        {
            return true;
        }

        public ICommand Addnum0 => new RelayCommond(Btn_Addnum0, CanLoginExecute);
        public ICommand Addnum1 => new RelayCommond(Btn_Addnum1, CanLoginExecute);
        public ICommand Addnum2 => new RelayCommond(Btn_Addnum2, CanLoginExecute);
        public ICommand Addnum3 => new RelayCommond(Btn_Addnum3, CanLoginExecute);
        public ICommand Addnum4 => new RelayCommond(Btn_Addnum4, CanLoginExecute);
        public ICommand Addnum5 => new RelayCommond(Btn_Addnum5, CanLoginExecute);
        public ICommand Addnum6 => new RelayCommond(Btn_Addnum6, CanLoginExecute);
        public ICommand Addnum7 => new RelayCommond(Btn_Addnum7, CanLoginExecute);
        public ICommand Addnum8 => new RelayCommond(Btn_Addnum8, CanLoginExecute);
        public ICommand Addnum9 => new RelayCommond(Btn_Addnum9, CanLoginExecute);

        public ICommand AddDot => new RelayCommond(Btn_AddDot, CanLoginExecute);
        public ICommand Powx => new RelayCommond(Btn_Powx, CanLoginExecute);
        public ICommand Sqrtx => new RelayCommond(Btn_Sqrtx, CanLoginExecute);
        public ICommand Clear => new RelayCommond(Btn_Clear, CanLoginExecute);
        public ICommand Backspace => new RelayCommond(Btn_Backspace, CanLoginExecute);
        public ICommand Plus => new RelayCommond(Btn_Plus, CanLoginExecute);
        public ICommand Sub => new RelayCommond(Btn_Sub, CanLoginExecute);
        public ICommand Mul => new RelayCommond(Btn_Mul, CanLoginExecute);
        public ICommand Div => new RelayCommond(Btn_Div, CanLoginExecute);
        public ICommand Equ => new RelayCommond(Btn_Equ, CanLoginExecute);
    }
}

CustomButton.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace MyCalculator
{
    public class CustomButton:Button
    {
        //依赖属性

        /// <summary>
        /// propdp +Tab键
        /// </summary>
        public CornerRadius ButtonCornerRadius
        {
            get { return (CornerRadius)GetValue(ButtonCornerRadiusProperty); }
            set { SetValue(ButtonCornerRadiusProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ButtonCornerRadius.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ButtonCornerRadiusProperty =
            DependencyProperty.Register("ButtonCornerRadius", typeof(CornerRadius), typeof(CustomButton));


        public Brush BackgroundHover
        {
            get { return (Brush)GetValue(BackgroundHoverProperty); }
            set { SetValue(BackgroundHoverProperty, value); }
        }

        // Using a DependencyProperty as the backing store for BackgroundHover.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BackgroundHoverProperty =
            DependencyProperty.Register("BackgroundHover", typeof(Brush), typeof(CustomButton));


        public Brush BackgroundPress
        {
            get { return (Brush)GetValue(BackgroundPressProperty); }
            set { SetValue(BackgroundPressProperty, value); }
        }

        // Using a DependencyProperty as the backing store for BackgroundPress.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BackgroundPressProperty =
            DependencyProperty.Register("BackgroundPress", typeof(Brush), typeof(CustomButton));
    }
}

CustomButtonStyle.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:MyCalculator">
    <Style TargetType="{x:Type local:CustomButton}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomButton}">
                    <Border x:Name="ButtonBorder" Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding ButtonCornerRadius}">
                        <TextBlock Text="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                               VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>

                    <!--触发器-->
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="ButtonBorder" Property="Background" Value="{Binding BackgroundHover,RelativeSource={RelativeSource TemplatedParent}}"/>
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="ButtonBorder" Property="Background" Value="{Binding BackgroundPress,RelativeSource={RelativeSource TemplatedParent}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

 

2025-06-17 15:28:29【出处】:https://www.cnblogs.com/dragonet-Z/p/18879217

=======================================================================================

posted on 2025-06-17 15:28  jack_Meng  阅读(35)  评论(0)    收藏  举报

导航