TabNavigation to select ListBox's first item - wpf

We're using tabnavigation for people, who dont want or can't use the mouse.
When i navigate via tab into the Listbox, the first item will be focused but not selected. When i tab again, the second item will be selected as well. For me it's a strange behavior.
How is it possible to select the first item on tab focus as well?
Thanks!
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Text="Focus"/>
<ListBox Grid.Row="1" KeyboardNavigation.TabNavigation="Continue">
<ListBoxItem Content="Test1"/>
<ListBoxItem Content="Test2"/>
<ListBoxItem Content="Test3"/>
</ListBox>
</Grid>
1st step
2nd step
3rd step

Generally, users won't expect the tabulator key to modify the current selection: They tab around to focus different controls, and then select items using the arrow keys and/or space. It seems like a bug in WPF's ListBox implementation that KeyboardNavigation.TabNavigation="Continue" not only modifies the current Keyboard Focus, but also selects an item.
If you still want the focused item to be selected, you could just add an event handler (or corresponding behavior) to your list box:
private void OnListBoxGotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is ListBoxItem listBoxItem)
{
listBoxItem.IsSelected = true;
}
}

Related

Override tab navigation for XAML ListBox

I want a list of items that are selectable, so naturally I chose ListBox. However the tab/arrowing behavior is not what I want. I need the tab behavior of ItemsControl without the arrow key functionality. So if I have three UIElements like:
ButtonA
ListBox
ButtonB
then the tab order will be:
ButtonA, ListBoxItem1, ... ListBoxItemN, ButtonB, ButtonA, ....
Unfortunately the default ListBox tab navigation makes the tab order:
ButtonA, ListBoxSelectedItem, ButtonB, ButtonA, ....
All is well if I use an ItemsControl, but ItemsControl has no selected item logic.
setting the KeyboardNavigation.TabNavigation in the ListBox to "Continue" should do it :
<StackPanel>
<Button Content="ButtonA"/>
<ListBox KeyboardNavigation.TabNavigation="Continue">
<ListBoxItem Content="One"/>
<ListBoxItem Content="Two"/>
<ListBoxItem Content="Three"/>
<ListBoxItem Content="Four"/>
</ListBox>
<Button Content="ButtonB"/>
</StackPanel>

Need to set DataContext of a UserControl from another UserControl both of which are on same WPF page

My WPF form is using multiple user controls. These represents unique forms. I need to give navigational kind of functionality.
Once a user clicks on EDIT button which is on UserControl A, I want to bind DataContext of UserControl B and Open this user control on master form.
This master form contains both the user control. How can I do that?
This is how my code looks like
<Window>
<TabControl Background="Transparent">
<TabItem Header="View Registration" Background="Transparent">
<my:BulkPersonRegistration x:Name="BulkPersonRegistrationForm" />
</TabItem>
<TabItem Header="Add/Update Person" Background="Transparent">
<my:PersonManager x:Name="PersonManagerForm" />
</TabItem>
</TabControl>
</Window>
BulkPersonRegistration user control calls a function for data binding to display a datagrid. Upon binding of a datagrid, edit button appears after every row. When user clicks edit button, I want PersonManager form to be binded by the object of edited row.
Problem is, BulkPersonRegistration form is not aware of PersonManagerForm. So I need a way to find out Parent form of BulkPersonRegistration i.e. Owner form and then find Personmanager form and finally setting it's data context. I think all of this needs to be done on BulkRegistration form. I would prefer doing this on Window rather than user control.
Please suggest.
You can create a layout along these lines...
<DockPanel>
<Button DockPanel.Dock="Top"
Content ="EDIT"
Height="30"
Width="150"
Click="ButtonBase_OnClick"
/>
<TextBlock DockPanel.Dock="Top" Name="Control1" DataContext="{Binding}" Background="Yellow"/>
<TextBlock DockPanel.Dock="Top" Name="Control2" Visibility="Collapsed" Background="Green"/>
<Rectangle DockPanel.Dock="Top"></Rectangle>
</DockPanel>
And in the click handler, you can set the data context of the second control...
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
Control2.DataContext = Control1.DataContext;
Control2.Visibility = Visibility.Visible;
}
This snippet makes the second control visible and makes the first control share its data context with the second control. You can actually set the control's data context to anything, but this snippet assumes it's the same data context. Setting the control's visibility will make it 'open'.
Hi You can achieve this simply by Binding using ElementName like this
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<local:UserControl1 x:Name="uc1"/>
<local:UserControl2 Grid.Row="1" DataContext="{Binding DataContext, ElementName=uc1}"/>
</Grid>
I hope this will help.

How to use up and down key to move treeviewitem selection in WPF

We create a HierarchicalDataTemplate for a treeview control. We can use mouse to click the tree item to change the selection. Now, we want to use keyboard up and down key to move the selection up and down. But it seems that it can't work. I searched a lot by Google and Stackoverflow, but failed.
So I created a new thread for this, could you please give me some help? thx.
<HierarchicalDataTemplate x:Uid="HierarchicalDataTemplate_1" x:Key="My_data_template" >
<ContentControl x:Uid="ContentControl_1" MouseDoubleClick="MouseDoubleClick" MouseRightButtonDown="MouseRightClick">
<Grid x:Uid="Grid_2" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Uid="ColumnDefinition_1" Width="*"/>
<ColumnDefinition x:Uid="ColumnDefinition_2" Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel x:Uid="StackPanel_3" HorizontalAlignment="Left" Orientation="Horizontal" Grid.Column="0">
<TextBlock x:Uid="TextBlock_13" Text="{Binding Name}" VerticalAlignment="Center" Margin="3,0,0,1" TextWrapping="NoWrap"/>
</StackPanel>
<CheckBox x:Uid="CheckBox_3" HorizontalAlignment="Right" Click="CheckBox_Click" Grid.Column="1" ToolTip="On/Off">
</CheckBox>
</Grid>
</ContentControl>
</HierarchicalDataTemplate>
Another question is that, I can use mouse to click the textblock to select the item, but when I use mouse click the CheckBox, the item can't be selected. Is there anyway to make treeview item selected when I click the CheckBox?
The way I applied the template to treeview is as following:
<TreeView x:Name="tv_pointcloud" x:Uid="TreeListView_1"
ItemTemplateSelector="{StaticResource DataAccessor}"
......
/>
public class DataAccessor : DataTemplateSelector
{
public DataAccessor()
{
Init();
}
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var element = container as FrameworkElement;
var template = element.FindResource("My_data_template") as DataTemplate;
return template;
}
......
}
thanks.
I had the same problem as you, in a WPF treeview I was unable to use Arrow Keys to navigate. The problem I found was the Checkbox that was getting the focus. So I set "Focusable = False for the checkbox, and now the navigation in the treeview is as expected:
<CheckBox Focusable="False" ... />
Keyboard commands and such are called gestures. Perhaps this is a good place to get you started:
Keyboard shortcuts in WPF

XAML ContextMenu gets bound to wrong row in a DataGrid

I have a XAML based ContextMenu bound to the rows in a datagrid. It works just fine - until the grid is scrolled!
This is the context menu for one of the controls in the visual tree or a DataGrid row.
<data:DataGridTemplateColumn Header="Customer Details" Width="*">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Background="Transparent"> <!-- allows click in entire cell -->
<controlsInputToolkit:ContextMenuService.ContextMenu>
<controlsInputToolkit:ContextMenu>
<controlsInputToolkit:MenuItem Header="{Binding CompletedOrderId,StringFormat='Create Reminder for order #\{0\}'}"
CommandParameter="{Binding}">
<controlsInputToolkit:MenuItem.Command>
<command:CreateReminderCommand/>
</controlsInputToolkit:MenuItem.Command>
<controlsInputToolkit:MenuItem.Icon>
<Viewbox>
<Image Width="19" Height="18" Source="../images/reminders.png" VerticalAlignment="Center"/>
</Viewbox>
</controlsInputToolkit:MenuItem.Icon>
</controlsInputToolkit:MenuItem>
<controlsInputToolkit:ContextMenu>
<controlsInputToolkit:ContextMenuService.ContextMenu>
......
The ICommand is CreateReminderCommand and the CommandParameter is bound to the data item for the row itself.
This works just fine - I can right click on a row and it will show me the correct text in the menu item 'Create Reminder for order 12345'.
Then I scroll the datagrid down a page. If I keep right clicking on items then suddenly I'll see the wrong order number for a row. I think what must be happening is this :
The DataGrid is reusing instances of MenuItem that it has previously created.
How can I force a refresh of the ContextMenu when it is displayed for an item that changes? There's no 'Update method on the ContextMenu or ContextMenuService.
This turned out to be a Silverlight bug related to element binding.
http://blogs.msdn.com/delay/archive/2010/05/11/we-ve-secretly-changed-this-control-s-datacontext-let-s-see-if-it-notices-workaround-for-a-silverlight-data-binding-bug-affecting-various-scenarios-including-datagrid-contextmenu.aspx
The solution provided here fixes the problem.

Silverlight 3 scroll textblock in code

i need to scroll the textblock text. For example, the textblock contains 700 words. These words are populated to the textblock from code behind as it could be a different 700 words depending on some "stuff". There is a textbox on this form as well. The user types the words in the textblock into the textbox. As they type i keep track of which word from the textblock they are on. However, not all the words in the textblock will fit in the textblock viewing area, so i need to scroll the textblock from code behind. How do i go about doing this.
I"m using silverlight 3.
Thanks shannon
might be useful to put some code in...
Here is the scrollviewer and text block
<ScrollViewer x:Name="svSourceText" Width="591" MaxHeight="202" VerticalScrollBarVisibility="Auto">
<TextBlock Height="202" Width="591" TextWrapping="Wrap"
x:Name="txtSource" FontSize="12" FontFamily="Fonts/Fonts.zip#Consolas" LineHeight="21.333"
/>
</ScrollViewer>
for starters.. when i add text into the txtSource, the scroll viewer doesn't change it's scroll bar to be the height needed.
Put the TextBlock in a scrollviewer. Capture the event when the user enters text into your TextBox. Check that it's valid for the word currently being captured and then scroll the TextBlock.
Here is an example. I'm just scrolling every time the user presses the space bar, you'd want to verify the validity of the word being entered.
XAML:
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<TextBox Name="txtInput" KeyUp="TextBox_KeyUp" Width="200" Grid.Row="0" />
<ScrollViewer Name="scrollViewer" Grid.Row="1" MaxHeight="25" MaxWidth="250" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Hidden">
<TextBlock>
One
<LineBreak />
Two
<LineBreak />
Three
<LineBreak />
Four
<LineBreak />
Five
</TextBlock>
</ScrollViewer>
</Grid>
And the code for the event 'KeyUp':
private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key.ToString().ToLower() == "space")
{
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + 15);
}
}
Just a thought, have you considered using the AutoCompleteBox control?
You could bind its ItemsSource to an ObservableCollection<string> that contains all the current words and can have words added or removed as necessary.
As the user types in the TextBox area of the AutoComplete the set of matching words appear in a drop down.
Perhaps you are doing something else but I thought just post this in case it turns out you trying to re-invent the wheel.

Resources