Text changed event of text box in a gridview - wpf

I am new in wpf, so i have a problem in my gridview.
I'm using a TextBox in the GridView . Basically, what I want to do is call a method every time the text in the box is edited. That is when the text is entered, the function will call. That is the text change event should work.

Use the TextChanged event.
.xaml:
<TextBox TextChanged="TextBox_TextChanged" ... />
.xaml.cs:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
string text = ((TextBox)sender).Text;
// call your function
}

Related

TextBlock binding to selected DataGrid Element

Does anyone know how to dynamically set the ElementName for textblock.text binding?
I have two Datagrids that have the same information but the second DataGrid is just a filter of the same datasource, but what I want is to bind text of a textblock to the selected item depending if the item was clicked in the main datagrid or the secondary datagrid.
I have the below code to bind the textblock to one datagrid but I would also like the same to happen if the user clicked an item in the secondDataGrid.
Is this possible?
<TextBlock Margin="29,0" Text="{Binding SelectedItem.Name, ElementName=MainDataGrid}"
It is possible, though I don't think this is the proper solution.
You can handle one of the DataGrids' events in the code-behind, where in the handler you can write the following code:
BindingOperations.SetBinding(textBlock, TextBlock.TextProperty,
new Binding("SelectedItem.Name")
{
ElementName = "DataGrid1"
});
Basically you reset the Binding on the TextBlock's Text property with this code, where:
textBlock is the name of your TextBlock;
with TextBlock.TextProperty you define that you want to work with the Text property on the TextBlock;
The third paramter is the new Binding itself. The constructor takes the Path of the Binding and then in the "body" I set the ElementName.
If DataGrid1 fires the event you set the ElementName to that DataGrid's name, if DataGrid2 fires the event then you set the ElementName to the second DataGrid's name.
SelectionChanged can be a good event to handle on both DataGrid, but if you want the TextBlock to update when you selected and element in the first then select another one in the second and then click back to the first element to update then you need to handle the GotFocus event as well.
Play a little bit with it and you will see what I mean.
My working example:
private void SetBindingOnTextBlock(string elementName)
{
BindingOperations.SetBinding(textBlock, TextBlock.TextProperty, new Binding("SelectedItem.Name")
{
ElementName = elementName
});
}
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SetBindingOnTextBlock("DataGrid1");
}
private void DataGrid_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
SetBindingOnTextBlock("DataGrid2");
}
private void DataGrid1_GotFocus(object sender, RoutedEventArgs e)
{
SetBindingOnTextBlock("DataGrid1");
}
private void DataGrid2_GotFocus(object sender, RoutedEventArgs e)
{
SetBindingOnTextBlock("DataGrid2");
}
UPDATE 1:
Set
IsSynchronizedWithCurrentItem="True"
on the DataGrids and it may solve your problem if ItemsSources are the same. (Not sure if this is what #dkozl meant) Originally I assumed that they are different.

How can I change textbox contents based on which control the mouse is hovering over in WPF?

I have a textbox and several custom controls. Each of the custom controls has a "hint text" property that should appear in the textbox when that control is hovered over.
In winforms I was able to just give the custom control a textbox property and change its text property with events, however in WPF it instead makes a new textbox when I give it a property.
So how can I get the desired functionality?
Assuming your custom controls all inherit from a common base type (which I have called CustomControl as an example)...
XAML:
<TextBox x:Name=TextBox/>
<Button VerticalAlignment="Bottom" Click="ButtonBase_OnClick" MouseEnter="UIElement_OnMouseEnter" MouseLeave="UIElement_OnMouseLeave">test</Button>
Code behind:
private void UIElement_OnMouseEnter(object sender, MouseEventArgs e)
{
TextBox.Text = ((CustomControl) sender).HintText;
}
private void UIElement_OnMouseLeave(object sender, MouseEventArgs e)
{
TextBox.Text = string.Empty;
}

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.

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));
}

WPF: Cannot set focus

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

Resources