我在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分配一个新值时,事件再次被触发,我的代码进入无限循环。 我究竟做错了什么?我该如何解决这个问题?
答案 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)
您必须使用某种flag
说textChangedFromCode
并在尝试从处理程序设置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.
}
}