[c#] Windows Phone 7 에뮬레이터에서 TextBox.TextChanged 이벤트가 두 번 발생합니다.

Windows Phone 7을 사용하기위한 매우 간단한 테스트 앱이 있습니다 . 표준 UI 템플릿 에 a TextBox및 a TextBlock를 추가했습니다 . 유일한 사용자 지정 코드는 다음과 같습니다.

public partial class MainPage : PhoneApplicationPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private int counter = 0;

    private void TextBoxChanged(object sender, TextChangedEventArgs e)
    {
        textBlock1.Text += "Text changed " + (counter++) + "\r\n";
    }
}

TextBox.TextChanged이벤트까지 연결되어 TextBoxChangedXAML에서 :

<TextBox Height="72" HorizontalAlignment="Left" Margin="6,37,0,0"
         Name="textBox1" Text="" VerticalAlignment="Top"
         Width="460" TextChanged="TextBoxChanged" />

그러나 에뮬레이터에서 실행할 때 키를 누를 때마다 (화면 키보드 또는 물리적 키보드, Pause를 눌러 후자를 활성화) 카운터가 두 번 증가하여 TextBlock. 내가 시도한 모든 것은 이벤트가 실제로 두 번 실행되고 있음을 보여 주며 이유를 모르겠습니다. 한 번만 구독된다는 것을 확인했습니다. MainPage생성자 에서 구독을 취소 하면 텍스트가 변경 될 때 아무 일도 일어나지 않습니다 (텍스트 블록에).

일반 Silverlight 앱에서 동등한 코드를 시도했지만 거기에서 발생하지 않았습니다. 나는 현재 이것을 재현 할 실제 전화가 없습니다. Windows Phone 7에서 이것이 알려진 문제라는 기록을 찾지 못했습니다.

누구든지 내가 뭘 잘못하고 있는지 설명 할 수 있습니까? 아니면 버그로보고해야합니까?

편집 : 이것이 두 개의 텍스트 컨트롤을 가질 가능성을 줄이기 위해 TextBlock완전히 제거 하고 TextBoxChanged 메서드를 단순히 증가 하도록 변경했습니다 counter. 그런 다음 에뮬레이터에서 실행하고 10 개의 문자를 입력 한 다음counter++; 줄에 중단 점 두었습니다 (디버거에 침입하여 문제를 일으킬 가능성을 제거하기 위해) counter-20으로 표시 됩니다.

편집 : 이제 Windows Phone 7 포럼에서 질문했습니다 .



답변

TextChangedWP7에서 이벤트가 두 번 발생 하는 이유는 TextBoxMetro 모양에 대해 템플릿이 지정 되는 방식의 부작용 입니다.

TextBoxBlend 에서 템플릿 을 편집하면 TextBox비활성화 / 읽기 전용 상태에 대한 보조가 포함 된 것을 볼 수 있습니다 . 이로 인해 부작용으로 이벤트가 두 번 발생합니다.

TextBox이러한 상태가 필요하지 않은 경우 템플릿을 변경하여 추가 (및 관련 상태) 를 제거 하거나 보조 TextBox.

이를 통해 이벤트는 한 번만 실행됩니다.


답변

나는 버그로 갈 것입니다. 주로 거기에 KeyDownKeyUp이벤트 를 넣으면 한 번만 실행된다는 것을 보여 주지만 TextBoxChanged이벤트는 두 번 발생합니다.


답변

그것은 나에게 버그처럼 들립니다. 해결 방법으로 항상 Rx의 DistinctUntilChanged. 고유 키를 지정할 수있는 오버로드가 있습니다.

이 확장 메서드는 관찰 가능한 TextChanged 이벤트를 반환하지만 연속 중복을 건너 뜁니다.

public static IObservable<IEvent<TextChangedEventArgs>> GetTextChanged(
    this TextBox tb)
{
    return Observable.FromEvent<TextChangedEventArgs>(
               h => textBox1.TextChanged += h, 
               h => textBox1.TextChanged -= h
           )
           .DistinctUntilChanged(t => t.Text);
}

버그가 수정되면 간단히 DistinctUntilChanged줄을 제거 할 수 있습니다 .


답변

좋은! 나는 관련 문제를 검색 하여이 질문을 발견했으며 내 코드 에서이 성가신 것을 발견했습니다. 이중 이벤트는 내 경우 더 많은 CPU 리소스를 먹습니다. 그래서이 솔루션으로 실시간 필터 텍스트 상자를 수정했습니다.

private string filterText = String.Empty;

private void SearchBoxUpdated( object sender, TextChangedEventArgs e )
{
    if ( filterText != filterTextBox.Text )
    {
        // one call per change
        filterText = filterTextBox.Text;
        ...
    }

}


답변

나는 이것이 항상 Compact Framework의 버그라고 생각합니다. WP7로 옮겨 졌을 것입니다.


답변

물론 버그처럼 보입니다. 텍스트가 변경 될 때마다 이벤트를 발생시키려는 경우 양방향 바인딩을 대신 사용해 볼 수 있습니다. 안타깝게도 키당 변경 이벤트가 발생하지 않습니다 (필드 초점을 잃는다). 필요한 경우 해결 방법은 다음과 같습니다.

        this.textBox1.TextChanged -= this.TextBoxChanged;
        textBlock1.Text += "Text changed " + (counter++) + "\r\n";
        this.textBox1.TextChanged += this.TextBoxChanged;


답변

면책 조항-나는 xaml 뉘앙스에 익숙하지 않으며 이것이 비논리적으로 들린다는 것을 알고 있습니다 … 어쨌든-내 첫 번째 생각은 textchangedeventargs가 아닌 평범한 eventargs로 전달하는 것입니다. 말이되지 않지만 도움이 될 수 있습니까? 버그 때문이거나 2 개의 이벤트 처리기 호출이 뒤에서 일어나기 때문에 이전에 이와 같은 이중 발사를 본 적이있는 것 같습니다.

빠르고 더러운 것이 필요하다면 xaml에 대한 경험이 없습니다. 다음 단계는 빠른 해결 방법으로 해당 텍스트 상자에 대한 xaml을 건너 뛰는 것입니다 … 버그를 정확히 찾을 수있을 때까지 해당 텍스트 상자를 C #으로 완전히 수행하거나 까다로운 코드 … 즉, 임시 솔루션이 필요한 경우.