How to show cursor immediately on app startup? - c#

My app takes a bit to start because the UI is pretty heavy. I want to show Cursors.AppWaiting cursor the moment the user double-clicks on the shortcut. So I pop Cursor.Current = Cursors.AppStarting; into the constructor of the main form. However, when I start the app, the cursor does not change until after the form is loaded.
Is there a way to change the cursor immediately after the user double-clicks the shortcut?

Well, you can do the work using a Background Worker and UseWaitCursor property to change cursor.
var bw = new BackgroundWorker();
UseWaitCursor = true;
bw.DoWork += (s, e) =>
{
//do work..
};
bw.RunWorkerCompleted += (s, e) =>
{
Invoke((Action)(() => UseWaitCursor = false));
};
bw.RunWorkerAsync();

Try adding
Application.DoEvents();
After changing the cursor.

Just collapse your MainGrid until the app is loaded
Converter Reference
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
XAML ElementReference
Visibility="{Binding Path=IsLoaded, Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"

Related

Make caret (cursor) stop blinking

How do I make the cursor in a TextBox stop blinking in WPF?
I have already tried to a MouseDown event on the parent, with one action, this.Focus();, which does not work.
You could have achieved this with HideCaret Method. However, since the WPF application cannot provide you handle for the TextBox Control (it only provides handle for Window), we cannot use HideCaret.
However, we could emulate the effect using WPF. The first step to achieve this would be disable the actual Caret. This can be done by changing the Color to transparent.
<TextBox x:Name="txtName" CaretBrush="Transparent" />
The Next step involve using a Canvas and Border to emulate the Cursor.
<Grid>
<TextBox x:Name="txtName" CaretBrush="Transparent" />
<Canvas>
<Border x:Name="Caret" Visibility="Collapsed" Canvas.Left="0" Canvas.Top="0" Width="1" Height="15" Background="Black"/>
</Canvas>
</Grid>
You need to ensure the Canvas overlap the Textbox
And in code-behind
txtName.SelectionChanged += (sender, e) => MoveCustomCaret();
txtName.LostFocus += (sender, e) => Caret.Visibility = Visibility.Collapsed;
txtName.GotFocus += (sender, e) => Caret.Visibility = Visibility.Visible;
Where MoveCustomCaret is defined as
private void MoveCustomCaret()
{
var caretLocation = txtName.GetRectFromCharacterIndex(txtName.CaretIndex).Location;
if (!double.IsInfinity(caretLocation.X))
{
Canvas.SetLeft(Caret, caretLocation.X);
}
if (!double.IsInfinity(caretLocation.Y))
{
Canvas.SetTop(Caret, caretLocation.Y);
}
}
Sample

UWP - Show textbox text highlight while textbox is out of focus

How do I prevent the textbox from hiding the selected text highlight when the textbox loses focus? The following line worked for WPF
textBox1.IsInactiveSelectionHighlightEnabled = true;
but what is the equivalent for UWP?
You can set the SelectionHighlightColorWhenNotFocused property either in Xaml or via code. You can set it to any color you want, I just used binding to make sure it's the same color as the SelectionHighlightColor to make it easy.
<TextBox Style="{StaticResource TextBoxLightStyle}" Name="TextBoxMain"
AcceptsReturn="True"
SelectionHighlightColorWhenNotFocused="{Binding SelectionHighlightColor, ElementName=TextBoxMain, Mode=OneWay}">
</TextBox>
As I know there is no equivalent in UWP for that. One of possible work-around solutions could be to use some image to keep selection highlighted. Here is sample code:
XAML:
<Border BorderThickness="2" BorderBrush="{ThemeResource TextBoxBorderThemeBrush}" Height="164" Width="684">
<TextBox x:Name="textBox" TextWrapping="Wrap" Text="TextBox" BorderThickness="0,0,0,0"/>
</Border>
C#:
private async void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
{
// clear background
textBox.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 255, 255, 255)); ;
// render image
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(textBox);
// set background
textBox.Background = new ImageBrush()
{
ImageSource = renderTargetBitmap
};
}
In focus:
Not in focus:
p.s. I'm updating background on SelectionChanged event, but actually you can create image on that event and update only on LostFocus event. It should be more efficient.

synchronously show and hide controls in windows phone 8

In my windows phone 8 app I want to show a message before loading some items from database. After loading I want to hide the message again.
for examle my XAMLcode is like this:
<Grid Name="layoutRoot">
<Button Content="load more..."
Click="loadmore_clicked"/>
<TextBlock Name="loadingMessage"
Visibility="Collapsed"
Text="loading..." />
<phone:LongListSelector ItemsSource="{Binding Students}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<TextBlock Margin="10"
Text="{Binding name}" />
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>
and in my c# code I am trying something like this:
private void loadmore_clicked(object sender, RoutedEventArgs e)
{
loadingMessage.Visibility = Visibility.Visible;
LoadMoreItemsForLongList(); // loading more items for the LongListSelector's ItemSource
loadingMessage.Visibility = Visibility.Collapsed;
}
The "loadingMessage" TextBlock never been shown. For testing I put Thread.Sleep() in the LoadMoreItemsForLongList() function. But it didn't work either.
My goal is to show a "loadingMessage" TextBlock before start loading more data to the LongListSelector and hide the "loadingMessage" TextBlock after finishing load of more data. How can I do that? any help will be appreciated.
Seems like that LoadMoreItemsForLongList is a blocking method. When visibility of the loadingMessage is set, it's visual apprearance won't get updated until control goes of the loadmore_clicked (which is running in UI thread) and UI can show the loadingMessage, but before that, it's Visibility set to Collapsed.
You run the LoadMoreItemsForLongList in another thread:
private void loadmore_clicked(object sender, RoutedEventArgs e)
{
loadingMessage.Visibility = Visibility.Visible;
Task.Run( () =>
LoadMoreItemsForLongList() // loading more items for the LongListSelector's ItemSource
).ContinueWith( () =>
loadingMessage.Visibility = Visibility.Collapsed;
);
}
But you need to be aware that all UI interactions in the LoadMoreItemsForLongList need to done in UI Thread. You may use Dispatcher:
void LoadMoreItemsForLongList() {
// Load list from DB
CoreWindow.GetForCurrentThread().Dispatcher.Current.RunAsync(
CoreDispatcherPriority.Normal, () => {
this.lstItems.ItemsSouce = ...;
});
}
But if you follow async design patterns and define LoadMoreItemsForLongList async, you can do this instead:
private async void loadmore_clicked(object sender, RoutedEventArgs e)
{
loadingMessage.Visibility = Visibility.Visible;
await LoadMoreItemsForLongListAsync();
loadingMessage.Visibility = Visibility.Collapsed;
}
This is the prefered way. and again, you still need to perfom UI actions of LoadMoreItemsForLongListAsync in UI thread.

WPF TreeView restores its focus after double click

I have a WPF TreeView with XAML shown below:
<TreeView x:Name="twElements">
<TreeView.Resources>
<v8r:IconTypeConverter x:Key="IconConverter"/>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="MouseDoubleClick" Handler="twElements_MouseDoubleClick" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ChildItems}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon, Converter={StaticResource IconConverter}}"/>
<TextBlock Text="{Binding Text}" Margin="3,0,0,0"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
The task is to open some form after double click on a child item.
code-behind for DoubleClick event:
private void twElements_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (e.Source is TreeViewItem && ((TreeViewItem)e.Source).IsSelected)
{
e.Handled = true;
var twi = (TreeViewItem)e.Source;
var Editable = twi.Header as IEditable;
if (Editable != null)
{
Window Editor = Editable.GetEditor();
Editor.Show(); // Editor is a WPF.Window
}
}
}
The problem: After desired window is opened, form with a treeview activates itself, making new window to go background.
How to make new window to remain active?
You probably need to let WPF finish the job of handling the current mouse click event(s) before you open the new Window. Let the new window be the next UI job by adding it to the current Dispatcher's queue like this:
(...)
//Editor.Show();
Action showAction = () => Editor.Show();
this.Dispatcher.BeginInvoke(showAction);
in constructor of new form set
this.Focus();
Also, does your new form should be Modal window? if yes use Editor.ShowDialog() instead of Editor.Show(); It will automatically solve issue with focus

using the dispatcher to load usercontrols in WPF

I have a user control that has a grid with like 2900 items in it, there is nothing I can do about this cause that is the way the business want's it... Obviously this is slow to load/render so I created this trick using the dispatcher, in the view model that handles the event (prism event... not a standard windows event).
public void ShowPopUp(Type viewType)
{
var waitScreen = new Controls.Views.SampleView();
var popUp = new ShellBlank();
popUp.Content = waitScreen;
popUp.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
popUp.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, new Action(delegate() {
popUp.Content = container.Resolve(viewType);})
);
popUp.ShowDialog();
}
It works just fine however on my SampleView (as it is called at the moment) there is an in-determinant progress bar however it never updates, like you know - the green bara going back and fourth... Here is the XAML for it.
<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Margin="12" FontSize="16" Foreground="WhiteSmoke" Content="Loading... Please wait"/>
<ProgressBar Grid.Row="1" IsIndeterminate="True" Width="280" Height="24"/>
</Grid>
</Border>
Is it something to do with the dispatcher not letting it update?
Anyone ever done something like this? got any suggestions?
Thanks!
My guess is that the Dispatcher thread is busy trying to render your control and hasn't been able to update the ProgressBar.
Is the popup window responsive? Try moving the window or adding a button and seeing if you can click on the button. This might help identify whether its a simple problem with the progress bar or the Dispatcher being too busy.
Actually I ended up doing was calling container.resolve on the view, I called called container.resolve on the view model, this could be done with a standard background worker - then in the RunWorkerCompleted with happens bank on the main thread I create the view passing in the view model that we happily waited for in the background and switch out the wait screen which of course wasn't impacted by our long running process. Here is the code.
AddVendorModalityViewModel viewModel;
var waitScreen = new Controls.Views.SampleView();
var popUp = new ShellBlank();
popUp.Content = waitScreen;
popUp.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
var bw = new BackgroundWorker() { WorkerReportsProgress = true, WorkerSupportsCancellation = true };
bw.DoWork += (s, e) =>
{
viewModel = container.Resolve<AddVendorModalityViewModel>();
e.Result = viewModel;
};
bw.RunWorkerCompleted += (s, e) =>
{
viewModel = (AddVendorModalityViewModel)e.Result;
AddVendorModalityView view = new AddVendorModalityView(viewModel);
popUp.Content = view;
};
bw.RunWorkerAsync();
popUp.ShowDialog();
Hope this is useful for someone... The general idea is create the ViewModel on a different thread cause it is the thing that will take forever to load etc...

Categories

Resources