事件TextChanged多次触发

时间:2014-04-08 18:08:01

标签: c# wpf windows-phone-8 windows-phone

我在Windows手机上的应用程序中有三个TextBox。我想在用户在其中任何一个中插入输入后立即更改这三个TextBox的数值。

我的xaml看起来像这样:

<TextBox x:Name="t_horizontal" InputScope="Number" TextChanged="cambio"/>
<TextBox x:Name="t_vertical" InputScope="Number" TextChanged="cambio" />
<TextBox x:Name="t_diagonal" InputScope="Number" TextChanged="cambio"/>

我在c#中的代码是:

private void cambio(object sender, TextChangedEventArgs e)
{
    TextBox modificado = sender as TextBox;
    if (modificado.Name == "t_horizontal")
    {
        this.ancho = Double.Parse(modificado.Text);
        this.diagonal = getDiagonal(this.ancho, this.alto);
    } 
    else if (modificado.Name == "t_vertical")
    {
        this.alto = Double.Parse(modificado.Text);
        this.diagonal = getDiagonal(this.ancho,this.alto);
    }
    else if (modificado.Name == "t_diagonal")
    {
        this.diagonal = Double.Parse(modificado.Text);
        this.ancho = getAncho(diagonal);
        this.alto = getAlto(diagonal);
    }
    t_vertical.Text = this.alto+"";
    t_horizontal.Text = this.ancho+"";
    t_diagonal.Text = this.diagonal+"";
}

我想当我为TextBoxes分配一个新值时,事件再次被触发,我的代码进入无限循环。 我究竟做错了什么?我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

您处于无限循环中,因为您更改了TextChanged事件中的文本,因此它再次触发它。 Rohit Vats answer因为TextChanged event 异步而无法正常工作 - 所以你的情况很活泼。为了更好地了解它是如何工作的,我通过添加SempahoreSlim并等待其他事件完成来改进Rohit的答案。另一个问题是只有在值发生变化时才会引发事件,因此我们必须检查是否要等待信号量。

private bool textChanged = false;
SemaphoreSlim sem = new SemaphoreSlim(0, 1);
private async void cambio(object sender, TextChangedEventArgs e)
{
    if (!textChanged)
    {
        TextBox modificado = sender as TextBox;
        if (modificado.Name == "t_horizontal")
        {
            this.ancho = Double.Parse(modificado.Text);
            this.diagonal = getDiagonal(this.ancho, this.alto);
        }
        else if (modificado.Name == "t_vertical")
        {
            this.alto = Double.Parse(modificado.Text);
            this.diagonal = getDiagonal(this.ancho, this.alto);
        }
        else if (modificado.Name == "t_diagonal")
        {
            this.diagonal = Double.Parse(modificado.Text);
            this.ancho = getAncho(diagonal);
            this.alto = getAlto(diagonal);
        }
        textChanged = true;
        if (t_vertical.Text != this.alto + "")
        {
            t_vertical.Text = this.alto + "";
            await sem.WaitAsync(); // wait until finished changing with skip (flag)
        }
        if (t_horizontal.Text != this.ancho + "")
        {
            t_horizontal.Text = this.ancho + "";
            await sem.WaitAsync(); // wait until finished changing with skip (flag)
        }
        if (t_diagonal.Text != this.diagonal + "")
        {
            t_diagonal.Text = this.diagonal + "";
            await sem.WaitAsync(); // wait until finished changing with skip (flag)
        }
        textChanged = false;
    }
    else sem.Release();
}

上面的代码很脏,但应该显示正在发生的事情(不要使用它 - 这只是一个例子),调试并使用它。

您还可以尝试通过取消订阅/订阅活动来简化:

private void cambio(object sender, TextChangedEventArgs e)
{
    TextBox modificado = sender as TextBox;
    if (modificado.Name == "t_horizontal")
    {
        this.ancho = Double.Parse(modificado.Text);
        this.diagonal = getDiagonal(this.ancho, this.alto);
    }
    else if (modificado.Name == "t_vertical")
    {
        this.alto = Double.Parse(modificado.Text);
        this.diagonal = getDiagonal(this.ancho, this.alto);
    }
    else if (modificado.Name == "t_diagonal")
    {
        this.diagonal = Double.Parse(modificado.Text);
        this.ancho = getAncho(diagonal);
        this.alto = getAlto(diagonal);
    }
    t_vertical.TextChanged -= cambio;
    t_horizontal.TextChanged -= cambio;
    t_diagonal.TextChanged -= cambio;
    t_vertical.Text = this.alto + "";
    t_horizontal.Text = this.ancho + "";
    t_diagonal.Text = this.diagonal + "";
    t_vertical.TextChanged += cambio;
    t_horizontal.TextChanged += cambio;
    t_diagonal.TextChanged += cambio;
}

当然,您的代码可能应该进行修改以防止出现这种情况。

答案 1 :(得分:1)

您必须使用某种flagtextChangedFromCode并在尝试从处理程序设置Text并在运行代码之前检查其值时设置它。

伪代码如下所示:

bool textChangedFromCode;
private void cambio(object sender, TextChangedEventArgs e)
{
   if (!textChangedFromCode) // Check for condition here.
   {
      ......
      textChangedFromCode= true; // Set the flag here before editing text value.

      t_vertical.Text = this.alto+"";
      t_horizontal.Text = this.ancho+"";
      t_diagonal.Text = this.diagonal+"";

      textChangedFromCode= false; // Reset the flag once done.
   }
}