WPF: Cannot set focus - wpf

I want that from the PreviewTextInput handler a new control is created and focus is set to it. But even after calling Focus() on the new control, the cursor is still in the old textbox.
The handler UserControl_PreviewTextInput is registered on the UserControl which contains this textbox if this matters.
private void UserControl_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
CodeLineControl el = new CodeLineControl();
container.Children.Insert(idx+1, el);
el.innerTextBox.Focus();
}
CodeLineControl is defined like that(simplified):
<UserControl ..>
<DockPanel Name="codeline" Background="AntiqueWhite" >
<TextBox Name="innerTextBox"/>
</DockPanel>
</UserControl>
Are there some limitations on Focus() that Iam not awre about? Am I not allowed to move Focus() away from a TextBox from a PreviewTextInput handler? Can't I set the focus on newly created elements?

This is the extension method I use for instead of Focus:
public static void BackgroundFocus(this UIElement el)
{
Action a = () => el.Focus();
el.Dispatcher.BeginInvoke(DispatcherPriority.Background, a);
}
No need to create a timer.

Create a DispatcherTimer that calls Focus on that textbox after a delay

Related

wpf window event continue raise after window is closed

I have a problem with wpf events.
In the xaml I have following combobox with selectionchanged event:
<ComboBox Grid.Column="1" Grid.Row="1" Name ="comboBox"
SelectedItem="{Binding CurrentEventBinding.ControlId, ValidatesOnDataErrors=True}"
ItemsSource="{Binding ControlsNames}" SelectionChanged="ComboboxSelectionChanged">
In the codebehind I have following code:
private void ComboboxSelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
(DataContext as EventBindingEditViewModel).VmCommands.UpdateSourceCommand.Execute(null);
}
And I have the following working scenario:
Window.ShowDialog(); -> ComboboxSelectedChanged (the event is raised) -> CloseWindow();
Then again: Window.ShowDialog(); -> ComboboxSelectedChanged (the event is raised twice)
And if in the immediate window I write sender.GetHashCode() it returns first time the hashcode for the combobox from current window, and at the second time it returns the hashcode of the 'died' window.
So the event is raised so many times as the window is showed. It looks like old comboboxes aren't disposed or something like that.
Hope you understand my problem.
Thanks in advance!
The cause is that you are using binding, and it's still working after window closing. Then you change selected item in one window, it's changing selected item in other window (which is closed) via bindings. To resolve this, you should set DataContext = null in closed window. Or you can use the same window every time, just not close it, but hide.
Give the combobox a name and subscribe to SelectionChanged from code instead of XAML. On Window closing, unsubscribe from the event to make sure that it get's disposed.
<ComboBox Name="MyComboBox"....... />
And then in code:
protected override void OnSourceInitialized(EventArgs e)
{
MyComboBox.SelectionChanged += ComboBoxSelectionChanged;
}
protected override void OnClosing(CancelEventArgs e)
{
MyComboBox.SelectionChanged -= ComboBoxSelectionChanged;
}
Do you create the window with new Window() everytime, or it is a singleton ? Make sure to unsubscribe in the same manner from all events that you subscribed. Otherwise, the window that you close will never be disposed.

Binding Button.IsEnabled to position of current in CollectionView

I am trying to bind the IsEnabled property of a button to properties of the window's CollectionViewSource. I am doing this to implement First/Previous/Next/Last buttons and want the First and Previous to be disabled when the view is on the first item etc.
I have the collection view source set up, UI controls binding to it correctly, with access to its view in code so the click event handlers work fine in navigating through the view.
<CollectionViewSource x:Key="cvMain" />
The DockPanel is the root element of the window
<DockPanel DataContext="{StaticResource cvMain}">
FoJobs is an observable collection, cvJobs is a CollectionView that I use in the button's click handler
private void Window_Loaded(object sender, RoutedEventArgs e) {
((CollectionViewSource)Resources["cvMain"]).Source = FoJobs;
cvJobs = (CollectionView)((CollectionViewSource)Resources["cvMain"]).View;
}
I have tried this but get a binding error "BindingExpression path error: '' property not found on 'object' ''ListCollectionView'"
<Button Name="cbFirst" Click="cbMove_Click" IsEnabled="{Binding Source={StaticResource cvMain}, Converter={StaticResource CurrPos2BoolConverter}}" />
I am trying to do with a converter first but figure a style with triggers would be more efficient, but cant get access to the collection view. Even though the underlying datacontext is set to a collection view source, the binding is passed to the converter as the view's source (if I dont explicity set the binding's Source, as above), which has no currency properties (CurrentPosition, Count etc).
Any help would be greatly appreciated.
Why don't you use a RoutedCommand for this(even if you don't use MVVM that is)?
say something like:
<Button x:Name="nextButton"
Command="{x:Static local:MainWindow.nextButtonCommand}"
Content="Next Button" />
and in your code-behind:
public static RoutedCommand nextButtonCommand = new RoutedCommand();
public MainWindow() {
InitializeComponent();
CommandBinding customCommandBinding = new CommandBinding(
nextButtonCommand, ExecuteNextButton, CanExecuteNextButton);
nextButton.CommandBindings.Add(customCommandBinding); // You can attach it to a top level element if you wish say the window itself
}
private void CanExecuteNextButton(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = /* Set to true or false based on if you want button enabled or not */
}
private void ExecuteNextButton(object sender, ExecutedRoutedEventArgs e) {
/* Move code from your next button click handler in here */
}
You can also apply one of the suggestions from Explicitly raise CanExecuteChanged() to manually re-evaluate Button.isEnabled state.
This way your encapsulating logic relating to the button in one area.

How to handle child event in parent control

In my main window, I have a child control(user control) which contains a text box . How can I handle the textchange event of the text box of child control in main(parent) window.
Please provide me some example with code as I am new to routing of events.
You should just be able to hook the event from the parent control. But since your parent control doesn't have a TextChanged event of its own, you'll need to use attached-property syntax:
<Window ...
TextBox.TextChanged="ChildTextBoxChanged">
and in your codebehind:
private void ChildTextBoxChanged(object sender, TextChangedEventArgs args)
{
...
}
You don't have to put the TextBox.TextChanged= on the Window specifically -- just any control that's a parent of the TextBox, i.e., any control that's a parent of your UserControl. The event will bubble up to each parent in turn, all the way up to the top-level Window, and can get handled anywhere along the way.
(Note that if anyone hooks the event and sets e.Handled = true, the event won't bubble past that point. Useful to know if you have handlers at multiple levels.)
this also helped me. I will have a event in the container of the child control and define the event in the code behind file. The event will handle all the text changed events for all the children.
<StackPanel TextBoxBase.TextChanged="test_TextChanged" Name="test">
<userControl/>
</StackPanel>
Create a event in your childcontrol -
public event TextChangedEventHandler TextChanged;
now add a handler for TextChanged event of TextBox in childcontrol -
private void TextBox_TextChanged(object sender, TextChangedEventArgs args)
{
if (TextChanged != null)
{
TextChanged.Invoke(this, args);
}
}
also update XAML for this handler -
<TextBox ... TextChanged="TextBox_TextChanged" ... />
Now, you have created a event in your childcontrol that fires when the Textbox's textchanged fires.
Now you only to add a handler for this event in mainwindow -
private void ChildControl_TextChanged(object sender, TextChangedEventArgs args)
{
//TODO: Add your further code here.
}

WPF UserControl with TextBox, use TextChanged event C#

I have a customer usercontrol that is a labeled TextBox (Border wrapped about a Label and a TextBox with the TextBox overlapping the label). I am finding few (working) examples on how to get the TextChanged function to work when called from my UserControl.
Just the textbox snippet:
<TextBox
FontSize="{Binding Path=DefaultFontSize}"
Style="{StaticResource WatermarkTextBox}"
Padding="{Binding Path=TextPadding}"
Tag="{Binding Path=TextValue}"
/>
I have tried using RoutedEventHandler like I did with my button's Click event, but it didn't work. How do I get it so when let's say I use on the window it is required:
<MyControl:LabeledTextBox
TextBoxChange="Some_Event"
TextValue="{Binding SomethingOrOther}"
/>
that it will fire off correctly and do the needed function
This question's really unclear. Do you want your user control to support a TextChanged event that gets raised when the text in the TextBox changes? If so, you need to implement it in the code-behind.
First, declare the event:
public event TextChangedEventHandler TextChanged;
Then, add an event handler to the TextBox:
<TextBox TextChanged="TextBox_TextChanged" ... />
and in the code-behind:
private void TextBox_TextChanged(object sender, TextChangedEventArgs args)
{
TextChangedEventHandler h = TextChanged;
if (h != null)
{
h(this, args);
}
}
If you are using MVVM (Or if your TextValue binding is binding to something you can get to and edit) you can put the logic you want executed in the setter.
So, lets say you are binding to a property MyTextBoxValue. Set the binding mode to two way in the XAML, and in the setter put the logic or call to another method.
If you want the code to fire every time you type, set UpdateSourceTrigger=PropertyChanged in XAML, if you want the code to fire only when text entry is "done" set UpdateSourceTrigger=LostFocus.

WPF- Is it possible to add an OnVerticalOffsetChanged event to a custom textbox?

Is there any way for me to do this?
You can tell when the VerticalOffset changes by adding a handler to the ScrollViewer.ScrollChanged event to your TextBox. Something like this:
<TextBox AcceptsReturn="True" ScrollViewer.ScrollChanged="TextBox_ScrollChanged" />
The TextBox uses a ScrollViewer internally, so it's ScrollChanged event will bubble up to the TextBox (where you can handle it). The event arguments include information about what changed, such as the VerticalChange (the amount that the control has scrolled vertically).
private void TextBox_ScrollChanged(object sender, ScrollChangedEventArgs e) {
System.Diagnostics.Debug.WriteLine(string.Format("************ {0}", e.VerticalChange));
}

Resources