Ignore user input when UI is busy - c#

I will simulate my problem by taking two buttons in a sample application. In my actual case I have a UserControl along with a tabcontrol. When a button is pressed on the UserControl I am trying to get the parent Window and disabling it and perform some work on the UI for 1 minute. After the UI is free I am enabling the parent window.
My problem is when the ParentWindow is disabled and when the user clicks on the tabcontrol, as long as the UI is busy it remains unresponsive. But as soon as the UI does its work, all the user input is being taken into account and it switches tabs by itself. I want to ignore user input when the UI is busy please help. Any suggestions?
In the sample application here is the xaml
<StackPanel Orientation="Vertical">
<Button Height="20" Width="180" Click="Button_Click"
>Hello</Button>
<Button Height="20" Width="180" Click="Button_Click_1">Do Nothing</Button>
</StackPanel>
In the xaml.cs file here is code. See that I am disabling the Window but when the button is pressed i get the hello message automatically after the UI is free.
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello");
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Window.GetWindow(this).IsEnabled=false;
Thread.Sleep(5000);
Window.GetWindow(this).IsEnabled=true;
}

just run your long-running-code in new thread
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
try
{
this.Dispatcher.Invoke(() =>
{
Window.GetWindow(this).IsEnabled = false;
});
Thread.Sleep(5000);
}
finally
{
this.Dispatcher.Invoke(() =>
{
Window.GetWindow(this).IsEnabled = true;
});
}
});
}
expected result

Related

UWP C# Switching frame content issues and crashes

I've struggled with this setup for couple of days and found a somewhat solution but I think it not how it supposed to work.
Here is my xaml page setup:
<Page
...
<SplitView IsPaneOpen="True" DisplayMode="Inline" OpenPaneLength="300">
<SplitView.Pane>
<Grid>
<ToggleButton x:Name="Edit" IsEnabled="False" Checked="Edit_Checked" Unchecked="Edit_Unchecked"/>
</Grid>
</SplitView.Pane>
<Frame x:Name="RightFrame">
</Frame>
</SplitView>
</Page>
Code for toggle button:
private void Edit_Checked(object sender, RoutedEventArgs e)
{
RightFrame.Navigate(typeof(SubPage1));
}
private void Edit_Unchecked(object sender, RoutedEventArgs e)
{
RightFrame.Navigate(typeof(SubPage2));
}
So basically the toggle button switches the splitview content. The SubPages are just blank pages. The problem is that app crashes when navigation occurs.
I've noticed when I put this before invoking navigation:
RightFrame.Content = null;
Thread.Sleep(1000);
Then everything works fine. So I need to clear frame content and wait for it to finish I guess. But I think it should be done automatically. Could some one explain what am I doing wrong here and how it should be done?
Please verify your code in SubPage1 and SubPage2 which might be creating the crashes, you can clear the resources when the page gets unloaded.
Alternatively, you can try below code:
private void Edit_Checked(object sender, RoutedEventArgs e)
{
RightFrame.Content = new SubPage1();
}
private void Edit_Unchecked(object sender, RoutedEventArgs e)
{
RightFrame.Content = new SubPage2();
}

Keyboard accelerator firing when writing to Textbox

Click event of Button is fired when pressing D while writing to Textbox.
Is there an elegant way how to suppress Keyboard Accelerator while Textbox is focused?
XAML:
<StackPanel Orientation="Vertical">
<TextBox></TextBox>
<Button Click="Button_Click" Content="Button with "D" as keyboard accelerator" Margin="0,10">
<Button.KeyboardAccelerators>
<KeyboardAccelerator Key="D"></KeyboardAccelerator>
</Button.KeyboardAccelerators>
</Button>
<TextBlock x:Name="ButtonClickCounter"></TextBlock>
</StackPanel>
C#:
int buttonClickCounter;
private void Button_Click(object sender, RoutedEventArgs e)
{
ButtonClickCounter.Text = $"Button clicked {++buttonClickCounter} times";
}
EDIT:
Why Accelerator with Modifier (Alt+D or Ctrl+D) is not solution?
I am creating video player and I found that one-key shortcuts are neat solution for fast operations with video player (same as in VLC).
Best Solution so far:
Creating custom KeyboardAccelerator, that checks if focus is set to text box. Only edit in code that need to be done is changing KeyboardAccelerator to AcceleratorWithHandledActionIfTextboxIsFocused.
public class AcceleratorWithHandleDActionIfTextboxIsFocused:KeyboardAccelerator
{
public AcceleratorWithHandleActionIfTextboxIsFocused()
{
Invoked += AcceleratorWithHandleActionIfTextboxIsFocused_Invoked;
}
private void AcceleratorWithHandleActionIfTextboxIsFocused_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
var focusedElement = FocusManager.GetFocusedElement();
if (focusedElement.GetType() == typeof(TextBox))
args.Handled = true;
}
}
part of XAML:
<Button.KeyboardAccelerators>
<custom:AcceleratorWithHandleDActionIfTextboxIsFocused Key="D"></KeyboardAccelerator>
</Button.KeyboardAccelerators>
I agree with #Thomas Weller in his comments as for not using a single letter as a keyboard accelerator...
But everybody has their own requirements, anyway, you could try to e.handle = true your event when textbox is focused.
Something like this:
public void Button_Click(object sender, ExecutedRoutedEventArgs e)
{
if (textBox.isFocused)
{
e.handled = true;
}
}

Display Loading gif while getting datas

I would like to display a loading gif in WPF while I'm getting datas in database and querying theses.
I Have a MainWindow with 2 usercontrols and my image/loading gif.
I suppose I must use BackgroundWork but I don't manage to make it works.
Thank you.
Assume the following XAML, with one hidden Image and one Button that pretends to load data:
<StackPanel Margin="20">
<Image
x:Name="loadingGif"
Height="30"
Source="Assets/Square.bmp"
Visibility="Hidden"
VerticalAlignment="Top"
HorizontalAlignment="Left" />
<Button
Content="Load"
VerticalAlignment="Top"
Click="OnGoClick" />
</StackPanel>
In the button's Click event handler, you make the Image visible and start a BackgroundWorker. Once the BackgroundWorker is done, hide the Imageagain:
private void OnGoClick(object sender, RoutedEventArgs e)
{
loadingGif.Visibility = Visibility.Visible;
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += OnDoWork;
worker.RunWorkerCompleted += OnRunWorkerCompleted;
worker.RunWorkerAsync();
}
private void OnDoWork(object o, DoWorkEventArgs args)
{
Task.Delay(2000).Wait(); // Pretend to work
}
private void OnRunWorkerCompleted(object o, RunWorkerCompletedEventArgs args)
{
loadingGif.Visibility = Visibility.Hidden;
}
(You need to be careful about where you change the Image.Visibility property; this needs to happen on the UI thread.)
You can use the task for long running function(loading you data)
LoadGif();
await Task.Run(() => LoadYourData());

Programatically set Focus to a TextBox in Windows Phone

In a Windows Phone app I have an TextBox and a Button. The user writes some text to the TextBox and taps the Button, the text from the TextBox is added to a list. The TextBox loses focus after the Button is tapped.
What I want to do is to set the focus back to the TextBox after the Button is tapped so the user can continue writing another text without needing to tap the TextBox.
I tried calling the Focus() method of the TextBox in the Button handler but this does not work. is there another, if any, way to do this?
When Button clicked try to add bollean flag = true. Then check this flag on event OnTextBoxLostFocus.
<TextBox x:Name="tb" Grid.Row="1" LostFocus="Tb_OnLostFocus"/>
<Button x:Name="btn" Click="Btn_OnClick" />
public partial class MainPage : PhoneApplicationPage
{
private bool flag;
public MainPage()
{
InitializeComponent();
}
private void Btn_OnClick(object sender, RoutedEventArgs e)
{
flag = true;
tb.Focus();
}
private void Tb_OnLostFocus(object sender, RoutedEventArgs e)
{
if (!flag) return;
tb.Focus();
flag = false;
}
}
Hope its help.
I have tried a lot of solutions, but this is the only one that works for me (Windows Phone 8.1 app).
First catch your TextBox's Loaded event, then call Focus(FocusState.Keyboard).
private void myTextBox_Loaded(object sender, RoutedEventArgs e)
{
myTextBox.Focus(FocusState.Keyboard);
}
Even I tried with lots of above solutions but none of them worked for me as am trying to focus on page load. Finally I got this solution and it worked.
private void txtBox_LayoutUpdated(object sender, EventArgs e)
{
txtBox.Focus();
}
What happens if you call:
yourTextBox.Select(0,0)
http://msdn.microsoft.com/en-us/library/system.windows.controls.textbox.select.aspx
you can accomplish this by programmatically giving it focus. This can be done by
calling its Focusmethod, although this call can fail (and return false) under certain conditions.
For example, you cannot set focus on a control from a page’s constructor; it’s too early. You can,
however, call it from a page’s Loadedevent.
The way that it worked best for me on the phone was, if I wanted to focus on a particular textbox when the page loaded:
private void OnPageLoaded(object sender, RoutedEventArgs e)
{
Dispatcher dispatcher = Deployment.Current.Dispatcher;
dispatcher.BeginInvoke(() => EnterLocationTextBox.Focus());
}
or if I just wanted it at a certain point. Just repeat these two lines:
Dispatcher dispatcher = Deployment.Current.Dispatcher;
dispatcher.BeginInvoke(() => EnterLocationTextBox.Focus());

Action on both button press and release

I can't get this straight: I have one button that I want one action for the press event and one action for release, I've searched everywhere and can't find an answer.
KeyDown, KeyUp or MouseLeftButtonDown doesn't work with button on windows phone 7.
First I tried combining GotFocus and Click clickmode release like this:
(As you can see I want Image1 to be shown while pressing button, and hidden when releasing the button)
xaml:
Button Click="button1_Click" ClickMode="Release" GotFocus="button1_GotFocus" Content="byt" Height="72" Margin="0,500,6,0" Name="button1" VerticalAlignment="Top"
private void button1_GotFocus(object sender, RoutedEventArgs e)
{
Image1.Visibility = System.Windows.Visibility.Collapsed;
}
private void button1_Click (object sender, RoutedEventArgs e)
{
Image1.Visibility = System.Windows.Visibility.Visible;
}
This works only one time and could work all the time if I could loose focus from the button when releasing it (tried searching for that as well)
The other thing I tried was changing the clickmode while pressing the button, but didn't get that to work either..
something like this:
private void button1_Click (object sender, RoutedEventArgs e)
{
Image1.Visibility = System.Windows.Visibility.Collapsed;
button1.SetValue(Button.ClickModeProperty, ClickMode.Release);
Image1.Visibility = System.Windows.Visibility.Visible;
}
(I know that the syntax is wrong somehow in the second one)
Would be grateful for help!
MouseLeftButtonDown / MouseLeftButtonUp do work on WP7. Obviously not named the best, but they do work on the device.
<TextBlock x:Name="ApplicationTitle" MouseLeftButtonDown="ApplicationTitle_MouseLeftButtonDown" MouseLeftButtonUp="ApplicationTitle_MouseLeftButtonUp"
Style="{StaticResource PhoneTextNormalStyle}"
Text="MY APPLICATION" />
You'll see Down gets fired, and then immediately Up.
private void ApplicationTitle_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
}
private void ApplicationTitle_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
}
Perhaps all you need is MouseLeftButtonDown/Up.
I used
Click="{x:Bind UpArrow_Click}"
ClickMode="Press"
PointerCaptureLost="Button_Release"
on a button. When button is pressed UpArrow_Click event occurs... when button is released Button_Release event occurs

Categories