Changing the cursor in WPF sometimes works, sometimes doesn't
Do you need the cursor to be a "wait" cursor only when it's over that particular page/usercontrol? If not, I'd suggest using Mouse.OverrideCursor:
Mouse.OverrideCursor = Cursors.Wait;
try
{
// do stuff
}
finally
{
Mouse.OverrideCursor = null;
}
This overrides the cursor for your application rather than just for a part of its UI, so the problem you're describing goes away.
WPF datagrid cursor doesn't change on column resize
Did you try to copy your first XAML snippet into a blank WPF project? Can you reproduce the issue then? I doubt it because I cannot.
As for your second snippet, you should either remove the ScrollViewer
or move it to another row by adding another RowDefinition
to the Grid
and increase the value of Grid.Row
attached property. Currently, it lays on top of the DataGrid
.
Try this:
<Window ...>
<Grid x:Name="grid_main" Height="Auto" Width="Auto" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DataGrid x:Name="dg" Grid.Row="1">
<DataGrid.Columns>
<DataGridTextColumn Header="Test1" Width="100"/>
<DataGridTextColumn Header="Test2" Width="100"/>
<DataGridTextColumn Header="Test3" Width="100"/>
</DataGrid.Columns>
</DataGrid>
<DockPanel Width="Auto" Height="Auto">
<Button x:Name="btn_loadSchema" Content="Load Schema" Grid.Row="0" Height="20" Width="85" DockPanel.Dock="Left"
Margin="5" />
<Button x:Name="btn_loadJSON" Content="Load JSON" Grid.Row="0" Height="20" Width="85" DockPanel.Dock="Left"
Margin="5" IsEnabled="False"/>
<Button x:Name="btn_saveJSON" Content="Save JSON" Grid.Row="0" Height="20" Width="85" DockPanel.Dock="Left"
Margin="5" IsEnabled="False"/>
<Label/>
</DockPanel>
</Grid>
</Window>
MVVM Wait Cursor how to set the.wait cursor during invocation of a command?
I am using it successfully in my application:
/// <summary>
/// Contains helper methods for UI, so far just one for showing a waitcursor
/// </summary>
public static class UIServices
{
/// <summary>
/// A value indicating whether the UI is currently busy
/// </summary>
private static bool IsBusy;
/// <summary>
/// Sets the busystate as busy.
/// </summary>
public static void SetBusyState()
{
SetBusyState(true);
}
/// <summary>
/// Sets the busystate to busy or not busy.
/// </summary>
/// <param name="busy">if set to <c>true</c> the application is now busy.</param>
private static void SetBusyState(bool busy)
{
if (busy != IsBusy)
{
IsBusy = busy;
Mouse.OverrideCursor = busy ? Cursors.Wait : null;
if (IsBusy)
{
new DispatcherTimer(TimeSpan.FromSeconds(0), DispatcherPriority.ApplicationIdle, dispatcherTimer_Tick, System.Windows.Application.Current.Dispatcher);
}
}
}
/// <summary>
/// Handles the Tick event of the dispatcherTimer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private static void dispatcherTimer_Tick(object sender, EventArgs e)
{
var dispatcherTimer = sender as DispatcherTimer;
if (dispatcherTimer != null)
{
SetBusyState(false);
dispatcherTimer.Stop();
}
}
}
This has been taken from here. Courtsey huttelihut.
You need to call the SetBusyState
method every time you think you are going to perform any time consuming operation. e.g.
...
UIServices.SetBusyState();
DoProcessing();
...
This will automatically change your cursor to wait cursor when the application is busy and back to normal when idle.
Change mouse cursor to stop pointer on hover on disabled button in WPF
Since you won't be able to trigger events with a disable control, I suggest placing a transparent rectangle over it, which will handle that for you:
<Button x:Name="Button1" IsEnabled="False"/>
<Rectangle Opacity="0" Fill="Transparent">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Button1, Path=IsEnabled}"
Value="False">
<Setter Property="Cursor" Value="No"/>
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
The rectangle is collapsed when button is not enabled, so that it would allow button events to trigger. When the button is enabled, rectangle becomes visible (with 0 opacity and transparent background) and causes No cursor to appear when moused over.
EDIT:
Per comments, here's a working sample (which also attempts to resolve an issue OP is having with enabled button canceling behavior):
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"
HorizontalAlignment="Center">
<!-- Regular Button-->
<Button Width="120" Height="22" Margin="5"/>
<!--Custom Button-->
<Grid Width="120" Height="22" Margin="5">
<Button x:Name="Button1" IsEnabled="False"/>
<Rectangle Opacity="0" Fill="Transparent">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Button1, Path=IsEnabled}"
Value="False">
<Setter Property="Cursor" Value="No"/>
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Grid>
</StackPanel>
</Grid>
</Window>
Here's the demo:
I recommend creating a custom control using similar XAML, or, at the very least, create a template, so that you may reuse it.
Is is possible to change cursor blink rate and cursor movement speed in wpf?
WPF basically respects Windows's control panel settings of the blink rate. So does Word 2019 on my system. If you want to change the rate on your textbox, your only option is to disable the built-in caret (text cursor), and draw it yourself.
The following is shamelessly stolen inspired by this article, with some kinks ironed out:
SelectionChanged
triggers too early when TextBox height is not a full multiple of line height causing buggy cursor positioning. Changed toLayoutUpdated
.Caret.Height
respects the text height, instead of hardcoded.
Now on to the magic. Try this on your MainWindow.xaml
:
<Grid x:Name="YouNeedAGridToContainTheTextBoxAndCanvas">
<TextBox x:Name="CustomTextBox"
FontSize="20"
AcceptsReturn="True" TextWrapping="Wrap"
CaretBrush="Transparent" />
<!--CaretBrush must be Transparent, as we will draw manually below-->
<Canvas ClipToBounds="True">
<Border x:Name="Caret"
Width="4"
Visibility="Collapsed"
Background="Transparent"> <!--Start drawing Transparent-->
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames
Storyboard.TargetProperty="Background.Color"
FillBehavior="HoldEnd">
<ColorAnimationUsingKeyFrames.KeyFrames>
<!--Ease to Red in 1sec-->
<EasingColorKeyFrame KeyTime="0:0:1.0" Value="Red"/>
<!--Ease back into Transparent in another 1sec-->
<EasingColorKeyFrame KeyTime="0:0:2.0" Value="Transparent" />
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
</Canvas>
</Grid>
You then need to manually update the drawing position by using code behind in your MainWindow.xaml.cs
:
public MainWindow() //Constructor
{
InitializeComponent();
CustomTextBox.LayoutUpdated += (_, _) => {
var rect = CustomTextBox.GetRectFromCharacterIndex(CustomTextBox.CaretIndex);
if (rect.IsEmpty) return;
Canvas.SetLeft(Caret, rect.Left);
Canvas.SetTop(Caret, rect.Top);
Caret.Height = rect.Height;
};
CustomTextBox.LostFocus += (_, _) => Caret.Visibility = Visibility.Collapsed;
CustomTextBox.GotFocus += (_, _) => Caret.Visibility = Visibility.Visible;
CustomTextBox.Focus();
}
Feel free to tweak the color animation, adding frames as needed and playing with the KeyTime
for faster/slower pulsing. Use <DiscreteColorKeyFrame>
instead of <EasingColorKeyFrame>
if you want a hard blink instead of pulsing.
WPF Wait Cursor With BackgroundWorker Thread
What seems to be happening here is that WPF is ignoring the Cursor setting on the disabled window. The following workaround seems to work: instead of disabling the window itself, disable the content of the window:
C#:
((UIElement)Content).IsEnabled = false;
Cursor = Cursors.Wait;
// and in RunWorkerCompleted handler:
((UIElement)Content).IsEnabled = true;
Cursor = Cursors.Arrow;
Visual Basic:
DirectCast(Content, UIElement).IsEnabled = False
Cursor = Cursors.Wait
' and in RunWorkerCompleted handler:'
DirectCast(Content, UIElement).IsEnabled = True
Cursor = Cursors.Arrow
Related Topics
How to Check If a Property Exists on a Dynamic Anonymous Type in C#
Starting and Stopping Iis Express Programmatically
How to Elegantly Deal with Timezones
Find the Next Tcp Port in .Net
How to Get the Development/Staging/Production Hosting Environment in Configureservices
How to Send an Email in .Net According to New Security Policies
Linq Aggregate and Group by Periods of Time
How to Mock Out a .Net Httpwebresponse
String.Isnullorwhitespace in Linq Expression
Why Does Environment.Exit() Not Terminate the Program Any More
Methodinvoker VS Action for Control.Begininvoke
How to Use Timezoneinfo to Get Local Time During Daylight Saving Time
Uploading and Downloading Large Files in ASP.NET Core 3.1
Best Practices for Serializing Objects to a Custom String Format for Use in an Output File
Differences Between Expandoobject, Dynamicobject and Dynamic