Попытка обновить одно текстовое поле из другого и наоборот С# Winforms

У меня есть два текстовых поля на Winform. Идея состоит в том, чтобы вводить градусы Фаренгейта в одно поле и отображать градусы Цельсия в другом при вводе данных пользователем, и наоборот.

У меня он работает нормально, используя метод «Оставить» текстового поля, но я пытался использовать метод TextChanged, чтобы не щелкать или нажимать кнопку для получения результата.

Проблема, с которой я столкнулся сейчас, заключается в том, что при обработке первого символа фокус перемещается на второе поле, которое запускает метод TextChanged.

Я попытался использовать отправителя, чтобы включить if(), но отправитель теперь является полем назначения.

Любые мысли, пожалуйста?

       private void TB_Fahrenheit_TextChanged(object sender, EventArgs e)
    {

        float C, F;

        if (TB_Fahrenheit.Text != "")
        {
            if (float.Parse(TB_Fahrenheit.Text) < 1.0F)
            {
                TB_Fahrenheit.Text = "0" + TB_Fahrenheit.Text;
            }

            F = float.Parse(TB_Fahrenheit.Text);
            C = ((F - 32) * 5) / 9;
            TB_Celcius.Text = C.ToString();
        }

    }

    private void TB_Celcius_TextChanged(object sender, EventArgs e)
    {
        float C, F;
        string SentBy = ((TextBox)sender).Name;

        MessageBox.Show(SentBy);
        return;

        if(SentBy != TB_Fahrenheit.Text)
        {

        if (TB_Celcius.Text != "")
        {
            if (float.Parse(TB_Celcius.Text) < 1.0F)
            {
                TB_Celcius.Text = "0" + TB_Celcius.Text;
            }

            C = float.Parse(TB_Celcius.Text);
            F = ((C * 9) / 5) + 32;
            TB_Fahrenheit.Text = F.ToString();
        }
        }

    }

    private void TB_Celcius_Enter(object sender, EventArgs e)
    {
        TB_Celcius.Clear();
        TB_Fahrenheit.Clear();
    }

    private void TB_Fahrenheit_Enter(object sender, EventArgs e)
    {
        TB_Celcius.Clear();
        TB_Fahrenheit.Clear();
    }

person Cimbian    schedule 05.08.2014    source источник


Ответы (4)


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

private void setSliderValue(int currentAudioSecond)
{
    valueFromTimer = true;
    //Do Stuff
    valueFromTimer = false;
}

Затем, когда значение изменяется на моем ползунке:

private void sliderAudio_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (!valueFromTimer)
    {
        //Do stuff  
    }
}

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

person Andrew Grinder    schedule 05.08.2014
comment
Отличная идея. Я использую аналогичный метод каждый раз, когда у меня есть проект с DataGrid или другим элементом пользовательского интерфейса, где я могу изменять элемент программно. Таким образом, я могу избежать запуска события, если я программно изменяю элемент, который пользователь также может редактировать. - person AdamMc331; 05.08.2014
comment
Андрей, я нашел что-то подобное, и теперь это работает для меня. Спасибо. Стив. - person Cimbian; 05.08.2014

Я бы просто подписался и отписался от события на обоих Событие Control.Enter и Событие Control.Leave.

Когда вы Enter используете FahrenheitTextBox, это деактивирует событие TextChanged вашего celsiusTextBox. То же самое произойдет, когда будет введен celsiusTextBox, ваше событие fahrenheitTextBox.TextChanged будет отменено, что позволит вам воспользоваться надлежащим событием, событием TextChanged, для достижения вашей цели.

В дополнение к этому я бы не рекомендовал использовать математические формулы в вашем графическом интерфейсе, так как вы можете ошибиться, и их трудно проверить. Было бы лучше иметь статический класс Convert с подходящими методами для нужного вам преобразования.

public static class Convert {
    public float ToFahrenheit(float celsius) {
        float f = celsius * 9 / 5 + 32;
        return f;
    }

    public float ToCelsius(float fahrenheit) {
        float c = (fahrenheit - 32) * 5 / 9;
        return c;
    }
}

Затем вы можете написать свои модульные тесты.

[TestMethod]
public void ZeroCelsiusShouldConvertTo32Fahrenheit() {
    // Given
    float expected 32.0;
    float celsius = 0.0;        


    // When
    var actual = Convert.ToFahrenheit(celsius);

    // Then
    Assert.AreEqual(typeof(float), actual);
    Assert.AreEqual(expected, actual);
}
person Will Marcouiller    schedule 05.08.2014
comment
Уилл, Спасибо. Я еще немного поискал, и я в основном делаю это сейчас, но устанавливаю логическое значение в качестве флага для события Enter. Я обнаружу флаг в методе TextChanged. Цените помощь. Стив. - person Cimbian; 05.08.2014

Я думаю, вы должны использовать Leave событие вместо TextChanged. Потому что оно возникает, когда

  1. вы изменяете фокус с помощью клавиатуры (TAB, SHIFT+TAB и т. д.), вызывая методы Select или SelectNextControl или задавая для свойства ContainerControl.ActiveControl текущую форму.

  2. При изменении фокуса с помощью мыши или вызова метода Focus.

person Lamloumi Afif    schedule 05.08.2014
comment
Спасибо, но это то, чего я пытаюсь избежать. Использование события Leave означает, что ничего не отображается, пока фокус не будет перемещен вручную. - person Cimbian; 05.08.2014
comment
@Cimbian: почему ты пытаешься этого избежать? - person Lamloumi Afif; 05.08.2014
comment
Потому что это выглядит лучше в том, что я делаю. По мере изменения ввода вывод также автоматически обновляется. - person Cimbian; 06.08.2014

Я бы предложил использовать событие KeyPress для вычисления значения в другом TextBox, что-то вроде этого, хотя вам нужно будет выполнить некоторую проверку формата для float.Parse, чтобы убедиться, что у вас есть числовое значение.

        private void TB_Fahrenheit_KeyPress(object sender, KeyPressEventArgs e)
    {
        float C, F;

        if (TB_Fahrenheit.Text != "")
        {
            if (float.Parse(TB_Fahrenheit.Text) < 1.0F)
            {
                TB_Fahrenheit.Text = "0" + TB_Fahrenheit.Text;
            }

            F = float.Parse(TB_Fahrenheit.Text);
            C = ((F - 32) * 5) / 9;
            TB_Celcius.Text = C.ToString();
        }
    }

    private void TB_Celcius_KeyPress(object sender, KeyPressEventArgs e)
    {
        float C, F;
        string SentBy = ((TextBox)sender).Name;


        if (TB_Celcius.Text != "")
        {
            if (float.Parse(TB_Celcius.Text) < 1.0F)
            {
                TB_Celcius.Text = "0" + TB_Celcius.Text;
            }

            C = float.Parse(TB_Celcius.Text);
            F = ((C * 9) / 5) + 32;
            TB_Fahrenheit.Text = F.ToString();
        }

    }
person LarzStarz    schedule 05.08.2014
comment
Я использую событие KeyPress для создания своей строки и проверки каждого ввода на наличие цифры, десятичного числа или знака, но строковое значение недоступно до тех пор, пока фокус не будет перемещен или через TextChanged (я думаю). - person Cimbian; 05.08.2014