Wait Cursor not shown on TextBox Enter pressed

huangapple go评论57阅读模式
英文:

Wait Cursor not shown on TextBox Enter pressed

问题

以下是您要的翻译部分:

XAML

<TextBox Text="{Binding Path=FilterProperty.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
    <TextBox.InputBindings>
        <KeyBinding Key="Enter" Command="{Binding SearchFieldPressEnterCommand}"/>
    </TextBox.InputBindings>
</TextBox>

<Button Command="{Binding Path=SearchFieldPressEnterCommand}"/>

该命令首先设置等待光标。

命令的第一行

Mouse.OverrideCursor = Cursors.Wait;
[其他代码]

我的问题是,当在 TextBox 中按 Enter 键时,命令代码会执行,但等待光标不会显示。单击按钮会运行相同的命令并显示等待光标。

有什么想法吗?

问候,
Glen


编辑:
以下是我在空的 .NET Core 3.1 WPF 应用程序中测试的最小可重现示例。行为相同:有时会显示等待光标,有时不会。

MainWindow.xaml(在代码中设置 DataContext)

<StackPanel Orientation="Horizontal" Height="30">
    <TextBox Width="200">
        <TextBox.InputBindings>
            <KeyBinding Key="Return" Command="{Binding DoSomethingCommand}"/>
        </TextBox.InputBindings>
    </TextBox>
    <Button Command="{Binding Path=DoSomethingCommand}" Content="Run" Width="100"/>
</StackPanel>

MainWindowViewModel

class MainWindowViewModel
{
    public ICommand DoSomethingCommand { get; }

    public MainWindowViewModel()
    {
        DoSomethingCommand = new Command(DoSomething);
    }

    private void DoSomething()
    {
        Mouse.OverrideCursor = Cursors.Wait;

        System.Threading.Thread.Sleep(1000);

        Mouse.OverrideCursor = null;
    }
}

Command

public class Command : ICommand
{
    private readonly Action _execute;

    public Command(Action execute)
    {
        _execute = execute;
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        _execute();
    }
}
英文:

I have a MVVM application with a TextBox that executes a command (defined in ViewModel) on Enter pressed. There also is a button that executes that command on click.

XAML

&lt;TextBox Text=&quot;{Binding Path=FilterProperty.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot;&gt;
	&lt;TextBox.InputBindings&gt;
		&lt;KeyBinding Key=&quot;Enter&quot; Command=&quot;{Binding SearchFieldPressEnterCommand}&quot;/&gt;
	&lt;/TextBox.InputBindings&gt;
&lt;/TextBox&gt;

&lt;Button Command=&quot;{Binding Path=SearchFieldPressEnterCommand}&quot;/&gt;

The command sets the wait cursor first.

First line of Command

Mouse.OverrideCursor = Cursors.Wait;
[other code]

My Problem is, that the command code is executed when pressing Enter in TextBox, but the wait cursor is not shown. Clicking the button runs the same command and shows the wait cursor.

Any ideas?

Greetings,
Glen


Edit:
Here is a minimal reproducable example I tested in an empty .NET Core 3.1 WPF Application. Same behavior: sometimes wait cursor is shown, sometimes not.

MainWindow.xaml (setting DataContext in code behind)

    &lt;StackPanel Orientation=&quot;Horizontal&quot; Height=&quot;30&quot;&gt;
        &lt;TextBox Width=&quot;200&quot;&gt;
            &lt;TextBox.InputBindings&gt;
                &lt;KeyBinding Key=&quot;Return&quot; Command=&quot;{Binding DoSomethingCommand}&quot;/&gt;
            &lt;/TextBox.InputBindings&gt;
        &lt;/TextBox&gt;
        &lt;Button Command=&quot;{Binding Path=DoSomethingCommand}&quot; Content=&quot;Run&quot; Width=&quot;100&quot;/&gt;
    &lt;/StackPanel&gt;

MainWindowViewModel

    class MainWindowViewModel
    {
        public ICommand DoSomethingCommand { get; }

        public MainWindowViewModel()
        {
            DoSomethingCommand = new Command(DoSomething);
        }

        private void DoSomething()
        {
            Mouse.OverrideCursor = Cursors.Wait;

            System.Threading.Thread.Sleep(1000);

            Mouse.OverrideCursor = null;
        }
    }

Command

    public class Command : ICommand
    {
        private readonly Action _execute;

        public Command(Action execute)
        {
            _execute = execute;
        }

        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            _execute();
        }
    }

答案1

得分: 0

以下是您要翻译的内容:

"Glen, thanks for MRE!
I see your problem now.

Firstly, the reason this effects TextBox and not Button, is due to something called Mouse Vanish, which is the internal name for a Windows OS setting.

https://superuser.com/questions/928839/what-does-the-hide-pointer-while-typing-feature-actually-do

And finally, the reason you don't see the cursor change to Wait is because there isn't enough time to make that happen before you suspend the UI Thread with your call to sleep, or in the real application, do your work.

The solution to is to first change the mouse cursor position to undo the vanish, and then do your busy work in a worker thread. Note that is example code and you might want to find a better way to move the mouse and do work in the background than what I have here.

class MainWindowViewModel
{
    public ICommand DoSomethingCommand { get; }

    public MainWindowViewModel()
    {
        DoSomethingCommand = new Command(DoSomething);
    }

    private void DoSomething()
    {
        var p = GetMousePosition();
        SetCursorPos(p.X, p.Y + 1);
        Mouse.OverrideCursor = Cursors.Wait;
        DoBusyWork();
    }

    private async void DoBusyWork()
    {
        await Busywork();
        Mouse.OverrideCursor = null;
    }

    public Task<bool> Busywork()
    {
        return Task.Run(() =>
        {
            var t = new TaskCompletionSource<bool>();
            System.Threading.Thread.Sleep(1000);
            t.SetResult(true);
            return t.Task;
        });
    }

    [DllImport("User32.dll")]
    private static extern bool SetCursorPos(int X, int Y);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool GetCursorPos(ref Win32Point pt);

    [StructLayout(LayoutKind.Sequential)]
    internal struct Win32Point
    {
        public Int32 X;
        public Int32 Y;
    };
    public static Point GetMousePosition()
    {
        var w32Mouse = new Win32Point();
        GetCursorPos(ref w32Mouse);

        return new Point(w32Mouse.X, w32Mouse.Y);
    }
}

希望这对您有所帮助!

英文:

Glen, thanks for MRE!
I see your problem now.

Firstly, the reason this effects TextBox and not Button, is due to something called Mouse Vanish, which is the internal name for a Windows OS setting.

https://superuser.com/questions/928839/what-does-the-hide-pointer-while-typing-feature-actually-do

And finally, the reason you don't see the cursor change to Wait is because there isn't enough time to make that happen before you suspend the UI Thread with your call to sleep, or in the real application, do your work.

The solution to is to first change the mouse cursor position to undo the vanish, and then do your busy work in a worker thread. Note that is example code and you might want to find a better way to move the mouse and do work in the background than what I have here.

class MainWindowViewModel
{
    public ICommand DoSomethingCommand { get; }

    public MainWindowViewModel()
    {
        DoSomethingCommand = new Command(DoSomething);
    }

    private void DoSomething()
    {
        var p = GetMousePosition();
        SetCursorPos(p.X, p.Y + 1);
        Mouse.OverrideCursor = Cursors.Wait;
        DoBusyWork();
    }

    private async void DoBusyWork()
    {
        await Busywork();
        Mouse.OverrideCursor = null;
    }

    public Task&lt;bool&gt; Busywork()
    {
        return Task.Run(() =&gt;
        {
            var t = new TaskCompletionSource&lt;bool&gt;();
            System.Threading.Thread.Sleep(1000);
            t.SetResult(true);
            return t.Task;
        });
    }        

    [DllImport(&quot;User32.dll&quot;)]
    private static extern bool SetCursorPos(int X, int Y);

    [DllImport(&quot;user32.dll&quot;)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool GetCursorPos(ref Win32Point pt);

    [StructLayout(LayoutKind.Sequential)]
    internal struct Win32Point
    {
        public Int32 X;
        public Int32 Y;
    };
    public static Point GetMousePosition()
    {
        var w32Mouse = new Win32Point();
        GetCursorPos(ref w32Mouse);

        return new Point(w32Mouse.X, w32Mouse.Y);
    }
}

huangapple
  • 本文由 发表于 2023年3月1日 16:24:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75601137.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定