Числа WPF / C # в TextBox рассчитываются динамически - PullRequest
1 голос
/ 12 июня 2011

ОК, так что я почти уверен, что нахожусь на правильном пути с этим небольшим приложением, но дайте мне знать.Пользователь вводит 3 из 4 чисел в 4 редактируемых текстовых поля, и недостающее число рассчитывается автоматически.Изображение приложения здесь:

http://www.peauproductions.com/images/lens_app.PNG

Я посмотрел на привязку данных, и я думаю, что мне нужно иметь значения, способные глобально измениться.Я хочу, чтобы значения динамически обновлялись / вычислялись, и у меня не было кнопки вычисления.

После того, как я заработал, мне нужно выполнить проверку проверки, чтобы убедиться, что логический ввод только (без текста), ивсплывающая подсказка, в которой говорится, что нужно ввести число.

Получение следующей ОШИБКИ прямо сейчас:

"Установить свойство" 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;
            }
        }
    }
}

Если вы можете подумать о более простом или более правильном способе выполнения того, что я пытаюсь сделать, пожалуйста, дайте мне знать (я только начал изучать этот материал 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));
            }
        }
    }
}

** ОШИБКАТеперь я получаю это StackOverflowException на get {} внутри двойных функций.Есть идеи?

Ответы [ 4 ]

2 голосов
/ 12 июня 2011

Исключение выдается, потому что строка

Text="{x:Static c:Variables.DistanceBox}"

- это что-то вроде

textBox.Text = Variables.DistanceBox;

Это не скомпилируется в C #. В XAML это исключение. Вместо этого вам следует создать свойства из ваших полей:

public double DistanceBox { get; set; }

И установите Variables как DataContext вашего окна, добавив

DataContext = new Variables();

в конструктор вашего окна (или обработчик события Loaded).

Затем вы используете привязки в вашем XAML (который использует конвертер для получения string с double с):

Text="{Binding DistanceBox}"

Для вызова Calc() при каждом изменении значения вы можете изменить свойство на

private double m_distanceBox;
public double DistanceBox
{
    get { return m_distanceBox; }
    set
    {
        m_distanceBox = value;
        Calc();
    }
}

Чтобы убедиться, что изменения в Variables отражены в текстовых полях, вы должны реализовать интерфейс INotifyPropertyChanged .

РЕДАКТИРОВАТЬ: C # код MainWindow:

public partial class MainWindow
{
    public MainWindw()
    {
        InitializeComponent();
        DataContext = new Variables();
    }
}
0 голосов
/ 12 июня 2011

Ваша ошибка при настройке текстовых значений:

YourTextBox.Text=YourValue;

в вашем случае:

LensNeeded.Text = WidthBased.ToString();
0 голосов
/ 12 июня 2011

Вы должны использовать привязку данных для своих текстовых полей.

  1. Измените свой класс Variables, чтобы выставить 4 значения как строковые свойства (вы не можете привязать данные к полям, только к свойствам):

    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
    }
    

    Убедитесь, что вы изменили свой метод Calc для чтения текущих значений из TextBox, поскольку привязка данных настроена на двустороннюю связь.Вам нужно будет преобразовать строковые значения обратно в double, используя метод double.Parse ():

    double d = double.Parse (stringValue);

  2. SetDataContext вашей Grid к экземпляру вашего класса переменных

  3. Привязать текст вашего TextBox к строковому свойству:

    Text = {Binding LensNeededValue}
    
0 голосов
/ 12 июня 2011

Хотите установить текст?В wpf вам нужно использовать метод invoke вместо установки свойства прямого текста.

...