UserControl BringIntoView() not working properly - c#

Background:
I have a usercontrol defined in a ScrollViewer along with a ContentControl, the ContentControl will be visible all the time, and within it there is a Button, when the button is clicked will set the usercontrol to Visible, and when the usercontrol shows (Visiblility="Visible") I want it to be scrolled into the view. I have
XAML
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="465">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl Content="{Binding MyOtherViewModel}" Width="960" ></ContentControl>
<local:MyView IsVisibleChanged="MyView_IsVisibleChanged" Grid.Row="1" Visibility="{Binding IsNonCompliant, Converter={StaticResource BooltoVisible}, UpdateSourceTrigger=PropertyChanged}" />
</ScrollViewer>
Code Behind
private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
(sender as Control).BringIntoView();
}
Problem: this is not working, or more precisely, my usercontrol scrolled into the view first then revert back to the bottom of the ScrollViewer in a blink.
Weird thing: show a messagebox before calling BringIntoView will correctly display my usercontrol into the middle of the view
Current hack solution: you can see this works even to close the Window immediately after its loaded
private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
Window ss = new Window();
ss.Loaded += new RoutedEventHandler(ss_Loaded);
ss.ShowDialog();
(sender as Control).BringIntoView();
}
private void ss_Loaded(object sender, RoutedEventArgs e)
{
(sender as Window).Close();
}
Question: I know there must be something else going on, but I just can't identify it, but I really want to know what happened when a window showing with ShowDialog? Is this because it refreshes the window so that the BringIntoView will happen only after the usercontrol been loaded? (Not as the problem I have now: BringIntoView happened first, and then the window get refreshed and put the scrollbar back to the top). And what is the correct fix for my problem?

It looks like BringIntoView called before my Usercontrol getting rendered, as a result when it gets fully rendered, the scrollbar is revert back to the top (as I have described in my question). And thanks for the answer from #Evgeny posted for another question, I get a better solution now (less hack maybe?). Still want to see if there are better solutions.
private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var border = (FrameworkElement)sender;
if (border.IsVisible)
{
//Window ss = new Window();
//ss.Loaded += new RoutedEventHandler(ss_Loaded);
//ss.ShowDialog();
using (BackgroundWorker bg = new BackgroundWorker())
{
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
Tuple<FrameworkElement, double> b = new Tuple<FrameworkElement, double>(border, border.Height);
bg.RunWorkerAsync(b);
}
}
}
private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
(e.Result as UserControl).BringIntoView();
}
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
int maxwait = 300 //not scrolled to the view is not a disaster, but if the program hangs forever it will be a disaster, so set this to prevent that from happening
while (maxwait!=0
&&
(e.Argument as Tuple<FrameworkElement, double>).Item1.ActualHeight != (e.Argument as Tuple<FrameworkElement, double>).Item2)
{
Thread.Sleep(1);
maxwait --;
}
e.Result = (e.Argument as Tuple<FrameworkElement, double>).Item1;
}

I cannot believe that using background worker is a correct solution for this! You can use LayoutUpdated event to easily find when control is loaded and finally displayed.
userControl.LayoutUpdated+=OnLayoutUpdated;
private bool loaded=false;
private void OnLayoutUpdated(object sender,EventArgs e)
{
if (!loaded && (view.ActualHeight > 0 || view.ActualWidth > 0))
{
// Unsubscribe or set a flag.
userControl.LayoutUpdated -= OnLayoutUpdated;
loaded = true;
}
}
So you can execute that code when layout is updated and height or width is set. This will means that control is loaded and displayed.
Than you can unsubscribe or set a flag that initialization is complated.

Related

Why when saving to Settings radio button states it keep loading the first radio button state and not the last radio button state changed?

When loading :
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
radioButtonWatchDirectory.IsChecked = Properties.Settings.Default.RadioButtonWatchDirectory;
radioButtonWatchFile.IsChecked = Properties.Settings.Default.RadioButtonWatchFile;
checkBoxIncludeSubdirectories.IsChecked = Properties.Settings.Default.IncludeSubDirectories;
textBoxFileDirectory.Text = Properties.Settings.Default.BrowseFolderDialog;
}
When setting and saving :
private void radioButtonWatchFile_Checked(object sender, RoutedEventArgs e)
{
Properties.Settings.Default.RadioButtonWatchFile = (bool)radioButtonWatchFile.IsChecked;
Properties.Settings.Default.Save();
}
private void radioButtonWatchDirectory_Checked(object sender, RoutedEventArgs e)
{
Properties.Settings.Default.RadioButtonWatchDirectory = (bool)radioButtonWatchDirectory.IsChecked;
Properties.Settings.Default.Save();
}
When running the application once i checked true the Watch File radio button no matter if i check the Watch Directory radio button next time i will run the application the Watch File radio button will be checked. like it's not remembering changing it to the Watch Directory radio button.
The Include Subdirectories is working fine.
I tried this when loading :
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
radioButtonWatchDirectory.IsChecked = Properties.Settings.Default.RadiosTesting;
radioButtonWatchFile.IsChecked = Properties.Settings.Default.RadiosTesting;
checkBoxIncludeSubdirectories.IsChecked = Properties.Settings.Default.IncludeSubDirectories;
textBoxFileDirectory.Text = Properties.Settings.Default.BrowseFolderDialog;
}
When saving :
private void RadiosTests(object sender, RoutedEventArgs e)
{
if((bool)radioButtonWatchFile.IsChecked)
{
Properties.Settings.Default.RadiosTesting = (bool)radioButtonWatchFile.IsChecked;
Properties.Settings.Default.Save();
}
if((bool)radioButtonWatchDirectory.IsChecked)
{
Properties.Settings.Default.RadiosTesting = (bool)radioButtonWatchDirectory.IsChecked;
Properties.Settings.Default.Save();
}
}
but always the radioButtonWatchFile is checked when running the application again.
When a radio button is unchecked, the Checked event is not fired again. So, when you select another option, the setting of the previously checked option is not changed.
You could additionally subscribe to the Unchecked event of each radiobutton in order to manage the state in your settings object.
However, it might be a better idea to save some consolidated state of the currently selected option, instead of saving each radiobutton state individually.
Answer to why it always selects the file option: because both IsChecked properties are assigned true but only one can legally be selected, the selection of the first radiobutton is reset when the second one is initialized.
If you would revert the order of loading, the other button would be selected (this code is not a solution, just a demonstration of your error the other way around)
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// reverse initialization order changes the outcome
radioButtonWatchFile.IsChecked = Properties.Settings.Default.RadiosTesting;
radioButtonWatchDirectory.IsChecked = Properties.Settings.Default.RadiosTesting;
// ...
}
€dit: example of managing the radiobutton state by name with a somewhat mvvm like approach.
Suppose you create a viewmodel for your mode selection:
// consider linking this viewmodel to your settings somehow
class ModeViewModel
{
public string SelectedMode { get; set; }
public bool WithSubdirectories { get; set; }
}
In your groupbox, listen to Checked events and establish a property to maintain your selected RadioButton state => Tag in this example. The checked event handler will be responsible for setting the Tag depending on the actual RadioButton selection. When a new selected RadioButton is assigned, the ModeViewModel is updated accordingly.
<GroupBox Name="ModeGroup" Header="Mode"
ToggleButton.Checked="RadioButtonChecked"
Tag="{Binding SelectedMode, Mode=OneWayToSource}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<RadioButton Name="WatchFile" Content="Watch File"/>
<RadioButton Name="WatchFolder" Content="Watch Directory"
Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left"/>
<CheckBox Content="Include Subdirectories" IsChecked="{Binding WithSubdirectories}"
Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right"/>
</Grid>
</GroupBox>
Checked event handler that maintains the Tag state depending on the selected RadioButton.Name
private void RadioButtonChecked(object sender, RoutedEventArgs e)
{
if (e.Source is RadioButton rb && sender is GroupBox gb)
gb.Tag = rb.Name;
}
Load the selected radiobutton state from a string, containing the name of a RadioButton.
// Initialize the datacontext with your ModeViewModel
public MainWindow()
{
InitializeComponent();
ModeGroup.DataContext = new ModeViewModel();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// Load from your settings instead
var selectedMode = nameof(WatchFolder);
if (!string.IsNullOrEmpty(selectedMode) &&
LogicalTreeHelper.FindLogicalNode(ModeGroup, selectedMode) is RadioButton checkedElement)
{
checkedElement.IsChecked = true;
}
}
If you tweak this example and actually use your settings as initialization source and backing store of your viewmodel, this should work for your scenario.
Working solution.
void radioButton_Checked(object sender, RoutedEventArgs e)
{
if ((bool)radioButtonWatchFile.IsChecked)
{
Properties.Settings.Default.RadioButtonWatchFile = true;
Properties.Settings.Default.RadioButtonWatchDirectory = false;
}
else
{
Properties.Settings.Default.RadioButtonWatchFile = false;
Properties.Settings.Default.RadioButtonWatchDirectory = true;
}
Properties.Settings.Default.Save();
}

Paragraph mark of UWP RichEditBox is not resized

With this code (Editor.Document.Selection.CharacterFormat.Size = 20;) I change the font size of a UWP RichEditBox in the Page_Loaded-handle. When I start typing some characters, everything works fine. But when I select the paragraph mark and then type something, this text appears in the wrong font size (10.5).
What I've tried is to expand the selection before setting the font size, but it seems that there is no paragraph mark when there's no text. But when the rich edit box is empty and I press Shift+Right Arrow ⟶ (as I would normally select the paragraph mark), the font size is set back to 10.5.
Is there any workaround to prevent that the font size is set back to 10.5 in any case?
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock x:Name="FontSizeBlock" Grid.Row="0"></TextBlock>
<RichEditBox x:Name="Editor" Grid.Row="1" SelectionChanged="HandleRichEditBox_SelectionChanged"></RichEditBox>
</Grid>
public sealed partial class MainPage : Page {
public MainPage() {
this.InitializeComponent();
this.Loaded += Page_Loaded;
}
private void Page_Loaded(object sender, RoutedEventArgs e) {
Editor.Document.Selection.SetRange(0, 1);
Editor.Document.Selection.CharacterFormat.Size = 20;
}
private void HandleRichEditBox_SelectionChanged(object sender, RoutedEventArgs e) {
FontSizeBlock.Text = "FontSize: " + Editor.Document.Selection.CharacterFormat.Size;
}
}
Is there any workaround to prevent that the font size is set back to 10.5 in any case?
For your requirement, you could force font size to 20 when you press Shift+Right. Please refer the following code.
private void HandleRichEditBox_SelectionChanged(object sender, RoutedEventArgs e)
{
FontSizeBlock.Text = "FontSize: " + Editor.Document.Selection.CharacterFormat.Size;
if (Editor.Document.Selection.CharacterFormat.Size == 10.5)
{
Editor.Document.Selection.SetRange(0, 1);
Editor.Document.Selection.CharacterFormat.Size = 20;
}
}
When further investigating my problem, I noted that my issue doesn't occur when there has already been some text in the RichEditBox which was deleted.
Therefore, I have tried to programmatically append, select and remove characters in the Page_Loaded-handle, and this approach worked for me.
private void Page_Loaded(object sender, RoutedEventArgs e) {
// set any character
Editor.Document.SetText(Windows.UI.Text.TextSetOptions.None, "a");
Editor.Document.Selection.Expand(Windows.UI.Text.TextRangeUnit.Paragraph);
Editor.Document.Selection.CharacterFormat.Size = 20;
Editor.Document.SetText(Windows.UI.Text.TextSetOptions.None, "");
}

SHIFT + Scroll to Scroll Horizontally in ScrollViewer UWP

I would like to enable holding down SHIFT on the keyboard while scrolling to scroll a ScrollViewer horizontally.
I learned from here that the PointerWheelChanged event is the one I am looking for. Handling that, however, doesn't work because the ScrollViewer handles it internally, so my handler is never called. To get around that, I used the AddHandler method, as described in the "Routed Events Overview" article.
This works... but appears to be running my code AFTER the ScrollViewerruns its internal code. The result of this is that the ScrollViewer content pans vertically, then horizontally. They appear to happen in that order, and setting e.Handled = true doesnt stop it.
Is there a way to "intercept" the scroll, so I can handle it with my own logic, thus allowing the ScrollViewer to pan horizontally if SHIFT is pressed? I recently asked a similar question (involving intercepting input to a control so I could handle it with my own logic) here, where the answer involved handling a different event, where that event took place prior to control running its own logic. I do not see a similar "pre stuff happening" event for the pointer scroll.
The code I have follows. Note that the ScrollViewer can scroll BOTH horizontally and vertically, as well as zoom:
<!-- Contained in Grid in a UserControl, if that's relevant -->
<ScrollViewer Name="MyCanvasScrollViewer"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
ZoomMode="Enabled"
ZoomSnapPointsType="Optional"
PointerWheelChanged="MyCanvasScrollViewer_PointerWheelChanged">
<!-- Content to pan -->
</ScrollViewer>
Code-behind:
// Constructor for the user contol.
public MyControl()
{
// Add the scroll wheel event handler and force it to run.
this.MyCanvasScrollViewer.AddHandler(ScrollViewer.PointerWheelChangedEvent, new PointerEventHandler(this.MyCanvasScrollViewer_PointerWheelChanged), true);
// Other un-related stuff omitted here...
}
// Event handler for the Pointer Wheel Changed event.
private void MyCanvasScrollViewer_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
{
// If SHIFT is pressed...
var keyState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Shift);
if ((keyState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down)
{
// Get the amount to scroll.
PointerPoint pointer = e.GetCurrentPoint(this.WallCanvasScrollViewer);
double scrollWheelDelta = pointer.Properties.MouseWheelDelta;
// Change the view in the scroll viewer.
this.MyCanvasScrollViewer.ChangeView(scrollWheelDelta, null, null, true);
// Mark event as handled.
e.Handled = true;
}
}
You could simply disable VerticalScrollMode in shift keydown and enable it on keyup. No need for pointerwheelchanged itself. It works perfectly fine.
Xaml
<ScrollViewer ZoomMode="Enabled" x:Name="MyScrollViewer" HorizontalScrollMode="Enabled" HorizontalScrollBarVisibility="Visible" >
<Image Height="600" Width="500" Source="/Assets/1.jpg"></Image>
</ScrollViewer>
//C# code
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
CoreWindow.GetForCurrentThread().KeyDown += MainPage_KeyDown;
CoreWindow.GetForCurrentThread().KeyUp += MainPage_KeyUp; ;
}
private void MainPage_KeyUp(CoreWindow sender, KeyEventArgs args)
{
if (args.VirtualKey == VirtualKey.Shift)
{
MyScrollViewer.IsScrollInertiaEnabled = true;
MyScrollViewer.VerticalScrollMode = ScrollMode.Enabled;
}
}
private void MainPage_KeyDown(CoreWindow sender, KeyEventArgs args)
{
if (args.VirtualKey == VirtualKey.Shift)
{
MyScrollViewer.IsScrollInertiaEnabled = false;
MyScrollViewer.VerticalScrollMode = ScrollMode.Disabled;
}
}
}

How to prevent listbox items being dragged if mouse down is on certain controls

I would like some advice on drag and drop operations of listbox items. Each of my items has a ComboBox, TextBox, CheckBox and Button, as shown below.
I use my drag/drop to reorder these and it is almost working correctly.
The main issue is that a drag operation on an item is occurring when a PreviewMouseLeftButtonDown and PreviewMouseMove event happens on one of the controls noted above.
My question is given the code below what's good way I can prevent this drag occuring when one of the controls is clicked on?
XAML:
<DataTemplate DataType="{x:Type helpers:Filter}">
<Border>
<Border>
<Grid>
<ComboBox />
<TextBox />
<CheckBox />
<Button />
</Grid>
</Border>
</Border>
</DataTemplate>
<ListBox x:Name="FilterList"
ItemsSource="{Binding Filters}"
helpers:DragDropHelper.IsDragSource="true"
helpers:DragDropHelper.IsDropTarget="true" />
C#:
public static readonly DependencyProperty IsDragSourceProperty =
DependencyProperty.RegisterAttached("IsDragSource", typeof(bool), typeof(DragDropHelper), new UIPropertyMetadata(false, IsDragSourceChanged));
private void DragSource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.sourceItemsControl = (ItemsControl)sender;
Visual visual = e.OriginalSource as Visual;
this.topWindow = Window.GetWindow(this.sourceItemsControl);
this.initialMousePosition = e.GetPosition(this.topWindow);
this.sourceItemContainer = sourceItemsControl.ContainerFromElement(visual) as FrameworkElement;
if (this.sourceItemContainer != null)
{
this.draggedData = this.sourceItemContainer.DataContext;
}
}
// Drag = mouse down + move by a certain amount
private void DragSource_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (this.draggedData != null)
{
// Only drag when user moved the mouse by a reasonable amount.
if (Utilities.IsMovementBigEnough(this.initialMousePosition, e.GetPosition(this.topWindow)))
{
this.initialMouseOffset = this.initialMousePosition - this.sourceItemContainer.TranslatePoint(new Point(0, 0), this.topWindow);
DataObject data = new DataObject(this.format.Name, this.draggedData);
// Adding events to the window to make sure dragged adorner comes up when mouse is not over a drop target.
bool previousAllowDrop = this.topWindow.AllowDrop;
this.topWindow.AllowDrop = true;
this.topWindow.DragEnter += TopWindow_DragEnter;
this.topWindow.DragOver += TopWindow_DragOver;
this.topWindow.DragLeave += TopWindow_DragLeave;
DragDropEffects effects = DragDrop.DoDragDrop((DependencyObject)sender, data, DragDropEffects.Move);
RemoveDraggedAdorner();
this.topWindow.AllowDrop = previousAllowDrop;
this.topWindow.DragEnter -= TopWindow_DragEnter;
this.topWindow.DragOver -= TopWindow_DragOver;
this.topWindow.DragLeave -= TopWindow_DragLeave;
this.draggedData = null;
}
}
}
I tend to initialise my Drag and Drop properties in a PreviewMouseDown event handler, but it's unwise to perform any other Drag and Drop operations in that handler, because the user might not be dragging... they might just have clicked.
Instead, it's better to handle the PreviewMouseMove event to initiate a Drag and Drop operation. Here is a simplified example:
private void DragSourcePreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
isMouseDown = true;
}
private void DragSourcePreviewMouseMove(object sender, MouseEventArgs e)
{
if (isMouseDown && IsConfirmedDrag(e.GetPosition(sender as ListBox)))
{
isMouseDown = false;
...
DragDrop.DoDragDrop(dragSource, data, DragDropEffects);
}
}
It is in the PreviewMouseMove event handler that you could check which UI element has been clicked on and determine whether you start the Drag and Drop operation or not. Try something like this:
private void DragSourcePreviewMouseMove(object sender, MouseEventArgs e)
{
ListBox dragSourceControl = (ListBox)sender;
HitTestResult result = VisualTreeHelper.HitTest(dragSourceControl,
Mouse.GetPosition(dragSourceControl));
UIElement draggedUIElement = result.VisualHit.GetParentOfType<ListBoxItem>();
bool isViable = AddYourViabilityConditionHere(draggedUIElement);
if (isMouseDown && IsConfirmedDrag(e.GetPosition(sender as ListBox)) && isViable)
{
isMouseDown = false;
...
DragDrop.DoDragDrop(dragSource, data, DragDropEffects);
}
}

Assigning event GotFocus to all TextBoxes in WPF-Aplication

I wanted to add GotFocus-Event to every Textbox in my WPF-Aplication, because its for Touch Devices and everytime a TextBox is in use the OSK should open. I got Problems with procedure adding the Event to my TextBoxes. The Aplication is already build for pc (I'm in an interhsip and my goal is it to bring this Apl. to Windows 8 Touch Devices).This is the link, where I got my Inspiration from: Add/Remove handler to textbox
and here is my Solution:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
foreach (Control tb in this.Controls)
{
if (tb is TextBox)
{
TextBox tb1 = (TextBox)tb;
tb1.GotFocus += TextBox_GotFocus;
}
}
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
KeyBoardManager.LaunchOnScreenKeyboard();
}
when I want to run this Code I have the following Error:
Error 1 'OSK_Test.MainWindow' does not contain a definition for
'Controls' and no extension method 'Controls' accepting a first
argument of type 'OSK_Test.MainWindow' could be found (are you missing
a using directive or an assembly reference?)
What have I got to do, that it works? And of course it's the same with LostFocus!
You can do better, add below code to app.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(TextBox),
TextBox.GotKeyboardFocusEvent, new RoutedEventHandler(TextBox_GotFocus));
base.OnStartup(e);
}
The problem as I see it is that you are using an answer meant for a Winforms application with a Wpf application, in the Winforms your controls can be added to the main form, therefore this.Controls works, in Wpf your MainWindow has a Content Property which can contain only one item, usually a Grid, Canvas or Panel of some kind. This object is where your TextBox's are located.
Note: this will work only if your TextBox's are children of the MainWindows LayoutControl and not Embedded any deeper if it is embedded deeper you will need to name the Panel that they are contained in and iterate through that, also I am not suggesting that this is the proper way to approach your problem, just trying to point out what your problem is:
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
foreach (Control tb in ((Panel)this.Content).Children)
{
if (tb is TextBox)
{
TextBox tb1 = (TextBox)tb;
tb1.GotFocus += TextBox_GotFocus;
tb1.LostFocus += tb1_LostFocus;
}
}
}
Based on OP's comment:
You will need to give your StackPpanel a name or use an existing one if one exists. i.e.
<StackPanel x:Name="MyStackPanel" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100">
<TextBox Height="23" TextWrapping="Wrap" Text="TextBox"/>
<TextBox Height="23" TextWrapping="Wrap" Text="TextBox"/>
<TextBox Height="23" TextWrapping="Wrap" Text="TextBox"/>
<TextBox Height="23" TextWrapping="Wrap" Text="TextBox"/>
<TextBox Height="23" TextWrapping="Wrap" Text="TextBox"/>
</StackPanel>
Usuage would be something like this:
public MainWindow()
{
InitializeComponent();
foreach (Control tb in MyStackPanel.Children)
{
if (tb is TextBox)
{
TextBox tb1 = (TextBox)tb;
tb1.GotFocus += TextBox_GotFocus;
tb1.LostFocus += tb1_LostFocus;
}
}
}
you can easily achieved it using user control with textbox inheritance .
public UserTextbox()
{
InitializeComponent();
this.GotFocus += (sender, args) =>
{
//your code here
};
}
This user control you can use every where in you project you want.
Add a GotFocus handler to your root element in your window.
Assuming your root element is a Grid, it would be
<Grid name="root" GotFocus="root_GotFocus">
In your code
private void root_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = e.OriginalSource as TextBox;
if(tb != null)
{
//do your thing
KeyBoardManager.LaunchOnScreenKeyboard();
}
}

Categories