Почему видимость WPF Grid задерживается, когда TextBox имеет фокус? - PullRequest
1 голос
/ 24 июля 2011

В следующем XAML панель редактирования всегда видна.OverlayGrid отображается только тогда, когда длинная операция была запущена нажатием клавиши F5.Визуальный эффект заключается в том, что панель editPanel будет выделена серым цветом, что приведет к длительному процессу.

<Window.InputBindings>
    <KeyBinding Key="F5" Command="{Binding Path=RefreshCommand}"/>
</Window.InputBindings>

<Grid>

    <StackPanel Name="editPanel">
        <TextBox>set focus here to see the problem.</TextBox>
        <CheckBox>set focus here to remove the problem.</CheckBox>
        <TextBlock Text="{Binding Path=Worker.Message}"/>
    </StackPanel>

    <Grid Name="overlayGrid" 
          Visibility="{Binding Path=Worker.Visibility}"
          Background="Gray" Opacity="0.5">

        <TextBox Text="{Binding Path=Worker.Message}" FontWeight="Bold" 
                 HorizontalAlignment="Center" VerticalAlignment="Center" 
                 />

    </Grid>

</Grid>

OverlayGrid отображается точно так, как ожидается, за исключением случаев, когда TextBox имеет фокус.Если TextBox имеет фокус, длительная операция выполняется до того, как вы увидите быстрое мерцание overlayGrid.Это как если бы код был следующим: проделайте долгую операцию, покажите overlayGrid, сверните overlayGrid.

Код ViewModel, который выполняет длинную операцию и изменяет видимость overlayGrid, выглядит следующим образом:

Sub Refresh()

    Me.Worker.Message = String.Format("Refresh started at {0}..", 
                                      Date.Now.ToString("hh:mm:ss.fff")
    )

    Me.Worker.Visibility = Visibility.Visible

    ' Give the UI a chance to update itself.
    System.Windows.Forms.Application.DoEvents()

    Console.WriteLine("Debug: " + Me.Worker.Message)

    ' Fake the long operation.
    System.Threading.Thread.Sleep(1000)

    Me.Worker.Message = String.Format("Refresh completed at {0}.", 
                                      Date.Now.ToString("hh:mm:ss.fff")
    )

    Me.Worker.Visibility = Visibility.Collapsed

    Console.WriteLine("Debug: " + Me.Worker.Message)

End Sub

Почему фактическая видимость overlayGrid задерживается, когда TextBox имеет фокус?Как мне обойти эту проблему?

1 Ответ

2 голосов
/ 24 июля 2011

AFAIK, использование System.Windows.Forms.Application.DoEvents() не рекомендуется даже в WinForms.Вы, конечно, не должны использовать это в WPF, даже если это работает (очевидно, это не так).

Вместо этого вам следует запустить длинную операцию в фоновом потоке, а затем использовать Dispatcher.Invoke() установить результат в пользовательском интерфейсе.Что-то вроде:

Sub Refresh()

    Me.Worker.Message = String.Format("Refresh started at {0}..",
                                      Date.Now.ToString("hh:mm:ss.fff")
    )

    Me.Worker.Visibility = Visibility.Visible

    Console.WriteLine("Debug: " + Me.Worker.Message)

    Task.Factory.StartNew(
        Function()
            ' Fake the long operation.
            System.Threading.Thread.Sleep(10000)

            Dispatcher.Invoke(
                Function()
                    Me.Worker.Message = String.Format("Refresh completed at {0}.",
                                                      Date.Now.ToString("hh:mm:ss.fff")
                    )

                    Me.Worker.Visibility = Visibility.Collapsed

                    Console.WriteLine("Debug: " + Me.Worker.Message)

                End Function)

        End Function)

End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...