2014-04-08 4 views
2

Windows Phone에서 내 응용 프로그램에 TextBox가 3 개 있습니다. 사용자가 입력을 입력 한 직후에이 세 TextBox의 숫자 값을 변경하고 싶습니다. 나는이 텍스트 상자에 대한 새 값을 할당 할 때이벤트 TextChanged 여러 번 발생

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+""; 
} 

는 것 같아요, 이벤트가 다시 발사된다 :

<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#에서 내 코드는 다음과 같습니다

내 XAML은 다음과 같습니다 내 코드가 무한 루프에 들어간다. 내가 뭘 잘못하고 있니? 이 문제를 어떻게 해결할 수 있습니까?

+0

올바른 [ViewModel] (http://stackoverflow.com/a/14382137/643085)을 만들고 적절한 [DataBinding] (http://msdn.microsoft.com/en-us/)을 사용하는 것이 좋습니다. library/ms752347 (v = vs.110) .aspx)과 같은 끔찍한 괴물이 있습니다. –

+0

고마워, @ HighCore, 나는 그렇게하려고 노력할 것이다. 그러나 wpf와 ViewModel을 처음 접했을 때, 나는 그 새로운 모델에 대한 나의 문제에 대한 어떤 해결책을 제안 하겠는가? – Monica

답변

2

는 다시 한번 발사되도록 당신이 TextChanged 이벤트에 텍스트를 변경 beacause를 당신은 무한 루프에 있습니다. TextChanged event비동기이므로 Rohit Vats answer이 작동하지 않습니다. 어떻게 작동하는지 더 잘 알기 위해 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; 
} 

.

+0

감사합니다 !! 훌륭한 대답, 그것은 많은 것들을 이해하는 데 도움이 ... ... – Monica

+0

@mara 오신 것을 환영합니다. 내가 도와 줘서 고마워. – Romasz

+1

@mara 당신은 아마 그 문제에 대한 모든 것을 알고있을 것이다. 그러나 나는 그것을 내 블로그에 조각으로 가져왔다. (http://www.romasz.net/watch-out-for-asynchronous-events/) 첫 번째 게시물로;). 아마도 조금 더 도움이 될 것입니다. 최고의 소원. – Romasz

1

일종의 flagtextChangedFromCode을 사용해야하고 코드를 실행하기 전에 텍스트를 처리기에서 설정하고 값을 확인하려고 할 때 설정해야합니다.

의사 코드는 다음과 같이 표시됩니다

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. 
    } 
} 
+0

이것은 작동하지 않습니다. 플래그를 다시 설정 한 후에도 여전히 'cambio'를 다시 호출합니다. – Monica

+0

그래, 여전히'cambio'를 호출 할 것이고, 그 이유는 내가'if (! textChangedFromCode)'에서 언급 한 것처럼 꼭대기에 여분의 체크를해야만 코드에서 호출되면 코드가 if 조건 하에서 이미 랩핑했기 때문에 실행한다. –

관련 문제