WPF/C#动态计算文本框中的数字

WPF/C#动态计算文本框中的数字,c#,wpf,dynamic,binding,textbox,C#,Wpf,Dynamic,Binding,Textbox,好的,我很确定我使用这个小应用程序是正确的,但是请告诉我。用户在4个可编辑文本框中输入4个数字中的3个,并自动计算缺失的数字。应用程序图片如下: 我已经研究了数据绑定,我认为我需要有能够全局更改的值。我希望这些值能够动态更新/计算,而不必有“计算”按钮 一旦我让它工作,我需要实现一个验证检查,以确保只输入一个布尔值(没有文本),并有一个弹出的工具提示说,输入一个数字 正在获取以下错误: “'Set property'System.Windows.Controls.TextBox.Text'引发

好的,我很确定我使用这个小应用程序是正确的,但是请告诉我。用户在4个可编辑文本框中输入4个数字中的3个,并自动计算缺失的数字。应用程序图片如下:

我已经研究了数据绑定,我认为我需要有能够全局更改的值。我希望这些值能够动态更新/计算,而不必有“计算”按钮

一旦我让它工作,我需要实现一个验证检查,以确保只输入一个布尔值(没有文本),并有一个弹出的工具提示说,输入一个数字

正在获取以下错误:

“'Set property'System.Windows.Controls.TextBox.Text'引发异常。行号'56'和行位置'51'。”

MainWindow.xaml代码:

<Window x:Class="ConverterApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ConverterApp" Height="360" Width="280"
    xmlns:c="clr-namespace:ConvertorApp;assembly=">

<Grid>
    <!--Outer Box + Title-->
    <TextBox Height="309" Width="248"
    Text=" Lens Calculator"
    IsReadOnly="True" 
    Margin="5,5,0,0"
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
    BorderThickness="2.0"
    FontSize="16" FontFamily="Verdana" FontWeight="Bold">
        <TextBox.BorderBrush>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                <GradientStop Color="Black" Offset="0" />
            </LinearGradientBrush>
        </TextBox.BorderBrush> 
    </TextBox>

    <!--Title Text-->
    <TextBox Height="50" Width="230"
    Text="Enter Image Width, Length and Either Distance or Lens Values Below"
    IsReadOnly="True" 
    Margin="14,29,0,0"
    TextWrapping="Wrap"
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
    FontSize="12" FontFamily="Verdana"  FontStyle="Italic"
    BorderThickness="0">        
    </TextBox>

    <TextBox Height="20" Width="230"
    Text="Must Be Same Units (in,ft,cm,mm)"
    IsReadOnly="True" 
    Margin="14,59,0,0"
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
    FontSize="10" FontFamily="Verdana" FontStyle="Italic"
    BorderThickness="0">
    </TextBox>

    <!--Distance-->
    <TextBox Height="20" Width="105"
    Text="Distance/Height:"
    IsReadOnly="True" 
    Margin="15,80,0,0"
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
    FontFamily="Verdana"
    BorderThickness="0">
    </TextBox>

    <TextBox x:Name="DistanceBox" Height="20" Width="50"
    Text="{x:Static c:Variables.DistanceBox}"
    Margin="125,80,0,0"
    MaxLength="5" 
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
    FontFamily="Verdana">
        <TextBox.BorderBrush>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                <GradientStop Color="Black" Offset="0" />
            </LinearGradientBrush>
        </TextBox.BorderBrush>
    </TextBox>

    <!--Image Width-->
    <TextBox Height="20" Width="90"
    Text="Image Width:"
    IsReadOnly="True" 
    Margin="15,105,0,0"
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
    FontFamily="Verdana"
    BorderThickness="0">
    </TextBox>

    <TextBox x:Name="WidthBox" Height="20" Width="50"
    Text="{x:Static c:Variables.WidthBox}"
    Margin="125,105,0,0"
    MaxLength="5" 
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
             FontFamily="Verdana">
        <TextBox.BorderBrush>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                <GradientStop Color="Black" Offset="0" />
            </LinearGradientBrush>
        </TextBox.BorderBrush>
    </TextBox>

    <!--Image Length-->
    <TextBox Width="95"
    Text="Image Length:"
    IsReadOnly="True" 
    Margin="15,130,0,161" HorizontalAlignment="Left"
    FontFamily="Verdana"
    BorderThickness="0">
    </TextBox>

    <TextBox x:Name="LengthBox" Height="20" Width="50"
    Text="{x:Static c:Variables.LengthBox}"
    Margin="125,130,0,0"
             MaxLength="5" 
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
             FontFamily="Verdana">
        <TextBox.BorderBrush>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                <GradientStop Color="Black" Offset="0" />
            </LinearGradientBrush>
        </TextBox.BorderBrush>
    </TextBox>

    <!--Lens Needed-->
    <TextBox Height="20" Width="90"
    Text="Lens (mm):"
    IsReadOnly="True" 
    Margin="15,155,0,0"
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
    FontFamily="Verdana"
    BorderThickness="0">
    </TextBox>

    <TextBox x:Name="LensNeeded" Height="20" Width="50"
    Text="{x:Static c:Variables.LensNeeded}"
    Margin="125,155,0,0"
             MaxLength="4" 
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
             FontFamily="Verdana">
        <TextBox.BorderBrush>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                <GradientStop Color="Black" Offset="0" />
            </LinearGradientBrush>
        </TextBox.BorderBrush>
    </TextBox>

    <!--Info-->
    <TextBox Height="70" Width="230"
    Text="The lens focal length value represents the estimated mm value for a 1/4 inch sensor (Playstation Eye).  A lower mm will give a wider Field of View (FOV), and a higher value less FOV. "
    IsReadOnly="True" 
    TextWrapping="Wrap"
    Margin="15,180,0,0"
    FontSize="11"
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
    FontFamily="Verdana"  FontStyle="Italic"
    BorderThickness="0">
    </TextBox>
    <TextBox Height="55" Width="230"
    Text="It is not recommend you use a lens of less than 2.5mm focal length with image tracking software due to distortion."
    IsReadOnly="True"
    FontSize="11"
    TextWrapping="Wrap"
    Margin="15,253,0,0"
    VerticalAlignment="Top"
    HorizontalAlignment="Left"
    FontFamily="Verdana"  FontStyle="Italic"
    BorderThickness="0">
    </TextBox>


</Grid>

MainWindow.xaml.cs代码:

using System;
using System.Windows;

namespace ConvertorApp
{
    public class Variables
    {
        public const double DistanceBox = 0;
        public const double WidthBox = 0;
        public const double LengthBox = 0;
        public const double LensNeeded = 0;
        public const double WidthBased = 0;
        public const double LengthBased = 0;

        public void Calc()
        {
            double WidthBased = 2.952*(DistanceBox/WidthBox);
            double LengthBased = 3.984*(DistanceBox/LengthBox);

            if (WidthBased < LengthBased)
            {
                double LensNeeded = WidthBased;
            }else{
                double LensNeeded = LengthBased;
            }
        }
    }
}
使用系统;
使用System.Windows;
名称空间转换器
{
公共类变量
{
公共常量双距离框=0;
公共常数双宽度框=0;
公共常数双长度框=0;
public const double lensneed=0;
public const double WidthBased=0;
公共常数双长度基=0;
公共无效计算()
{
双宽度基=2.952*(距离框/宽度框);
基于双长度的=3.984*(距离框/长度框);
if(基于宽度<基于长度)
{
双透镜需要=基于宽度;
}否则{
双LensNeed=基于长度的;
}
}
}
}
如果你能想出一个更简单,或更正确的方法来进行我的尝试,请让我知道(我刚刚开始学习WPF/C的东西)。谢谢


更新:

以下是后台代码,显示了以下建议的更改:

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace ConverterApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new Variables();
        }
    }

    public class Variables : INotifyPropertyChanged
    {
        // Declare the PropertyChanged event.
        public event PropertyChangedEventHandler PropertyChanged;

        private double m_distanceBox;
        public double DistanceBox
        {
            get { return m_distanceBox; }
            set
            {
                m_distanceBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property 
                // is updated.
                NotifyPropertyChanged("DistanceBox");
            }
        }

        private double m_widthBox;
        public double WidthBox
        {
            get { return m_widthBox; }
            set 
            {
                m_widthBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property 
                // is updated.
                NotifyPropertyChanged("WidthBox");
            }  
        }

        private double m_lengthBox;
        public double LengthBox
        {
            get { return m_lengthBox; }
            set
            {
                m_lengthBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property 
                // is updated.
                NotifyPropertyChanged("LengthBox");
            } 
        }

        private double m_lensBox;
        public double LensNeeded
        {
            get { return m_lensBox; }
            set
            {
                m_lensBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property 
                // is updated.
                NotifyPropertyChanged("LensNeeded");
            } 
        }

        public void Calc()
        {
            double WidthBased = 2.95 * (DistanceBox / WidthBox);
            double LengthBased = 3.98 * (DistanceBox / LengthBox);

            if (WidthBased < LengthBased)
            {
                LensNeeded = Math.Round(WidthBased,2);
            }else{
                LensNeeded = Math.Round(LengthBased,2);
            }
        }

        // NotifyPropertyChanged will raise the PropertyChanged event, 
        // passing the source property that is being updated.
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,
                    new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
使用系统组件模型;
命名空间转换器应用程序
{
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
DataContext=新变量();
}
}
公共类变量:INotifyPropertyChanged
{
//声明PropertyChanged事件。
公共事件属性更改事件处理程序属性更改;
专用双m_距离盒;
公共双测距箱
{
获取{return m_distanceBox;}
设置
{
m_距离框=值;
//修改calc以读取文本值
计算();
//当源属性更改时调用NotifyPropertyChanged
//已更新。
NotifyPropertyChanged(“距离框”);
}
}
专用双m_宽度盒;
公用双宽度箱
{
获取{return m_widthBox;}
设置
{
m_widthBox=数值;
//修改calc以读取文本值
计算();
//当源属性更改时调用NotifyPropertyChanged
//已更新。
NotifyPropertyChanged(“宽度框”);
}  
}
私人双m_长箱;
公共双长箱
{
获取{return m_lengthBox;}
设置
{
m_lengthBox=数值;
//修改calc以读取文本值
计算();
//当源属性更改时调用NotifyPropertyChanged
//已更新。
NotifyPropertyChanged(“长度框”);
} 
}
私人双m_lensBox;
公共双透镜
{
获取{return m_lensBox;}
设置
{
m_lensBox=值;
//修改calc以读取文本值
计算();
//当源属性更改时调用NotifyPropertyChanged
//已更新。
NotifyPropertyChanged(“LensNeed”);
} 
}
公共无效计算()
{
双宽度基=2.95*(距离框/宽度框);
双长度基=3.98*(距离框/长度框);
if(基于宽度<基于长度)
{
LensNeed=数学圆(基于宽度,2);
}否则{
LensNeed=数学圆(基于长度,2);
}
}
//NotifyPropertyChanged将引发PropertyChanged事件,
//传递正在更新的源属性。
public void NotifyPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
{
财产变更(本,
新PropertyChangedEventArgs(propertyName));
}
}
}
}

**我现在得到的错误是双精度函数中get{}上的StackOverflowException。有什么想法吗?

要设置文本吗?在wpf中,您需要使用invoke方法,而不是设置直接文本属性。

YourTextBox.Text=YourValue;
LensNeeded.Text = WidthBased.ToString();
public class Variables
{
    // code as in your example
    public string LensValueNeeded 
    { 
      get { return LensNeeded.ToString(); }
      set { Calc(); }  // modify calc to read the text values
    }

    /// same for the other 3 values
}
Text = {Binding LensNeededValue}
Text="{x:Static c:Variables.DistanceBox}"
textBox.Text = Variables.DistanceBox;
public double DistanceBox { get; set; }
DataContext = new Variables();
Text="{Binding DistanceBox}"
private double m_distanceBox;
public double DistanceBox
{
    get { return m_distanceBox; }
    set
    {
        m_distanceBox = value;
        Calc();
    }
}
public partial class MainWindow
{
    public MainWindw()
    {
        InitializeComponent();
        DataContext = new Variables();
    }
}