How do I set tab ordering in WPF? I have an ItemsControl with some items expanded and some collapsed and would like to skip the collapsed ones when I'm tabbing.
Any ideas?
If you want to explicitly set the tab ordering for elements in your form, the following attached property is supposed to help:
<Control KeyboardNavigation.TabIndex="0" ... />
I say "supposed to help" as I haven't found it very reliable though I probably need to read more about how it is intended to be used. I only post this half baked answer because no one else mentioned this property.
Note that in Win RT, the property is just TabIndex="0".
You can skip elements in the tab sequence by setting KeyboardNavigation.IsTabStop on the element in XAML.
KeyboardNavigation.IsTabStop="False"
You can setup a trigger that would toggle this property based on the expanded state.
<Control KeyboardNavigation.TabIndex="0" ... /> Works perfectly fine...
For example-
<ComboBox Height="23"
Margin="148,24,78,0"
Name="comboBoxDataSet"
VerticalAlignment="Top"
SelectionChanged="comboBoxDestMarketDataSet_SelectionChanged"
DropDownOpened="comboBoxDestMarketDataSet_DropDownOpened"
KeyboardNavigation.TabIndex="0" />
<ComboBox Height="23"
Margin="148,56,78,0"
Name="comboBoxCategory"
VerticalAlignment="Top"
SelectionChanged="comboBoxDestCategory_SelectionChanged"
DropDownOpened="comboBoxDestCategory_DropDownOpened"
KeyboardNavigation.TabIndex="1" />
Will allow you to navigate through these two combo boxes using TAB key.
I think there is a much easier solution here,
at the top within your control or window or whatever, you could add:
KeyboardNavigation.TabNavigation="Cycle"
This also automaticaly ignores the collapsed tabs.
Another alternative that has worked for me in the past is to simply remove all explicit TabIndex statements, and let the controls use the order that they're declared in XAML work their magic.
This, of course, may require you to reorder your controls. But this is a simple copy-paste operation.
You can use KeyboardNavigation.TabNavigation="None" to completely skip the Tabbing for specific control.
Related
I'm looking to create a UI element in a WPF XAML UserControl with something that looks and works roughly like Google Suggest - a TextBox with a ListBox that appears beneath it showing suggestions that match the text entered in the TextBox. In simplified form, my XAML looks like this:
<StackPanel>
[...controls above...]
<TextBox ... />
<ListBox ItemsSource="{Binding SearchHints}"
Visibility="{Binding HasSearchHints}" MaxHeight="100" />
[...controls below...]
</StackPanel>
What I'm struggling to achieve is I want the ListBox to float above any content that may come below it, much like the dropdown part of a ComboBox does. Currently it pushes any controls below it downwards. I figure this must be possible because the ComboBox control essentially does exactly what I want to do. In CSS it would be a matter of setting the element to position:relative but there doesn't seem to be an immediately obvious equivalent in XAML. Any ideas?
Used Icepickle's comment - the element did exactly what I wanted.
I am developing an app for sending some feedback.
Basically I'm trying to make a TextBox for comments, but I'm used to the WinForms MultiLine=true. I've set MinLines to 3, which is getting there, but preferably I'd like it if the user is able to type wherever in this block - like press enter and do dot points sort of thing. For example:
- Item 1 blah
- Item 2 blahlb lahbvl d
But at the moment the text all stays on one line.
- Item 1 blah - Item 2 blahb blahb blah
These comments will then help fill the body of an email which is sent. It may be pointless if I can't easily keep the same formatting when putting this string into the email body string (so that it looks like it does when sent as it does when typed).
Can I achieve what I'm after or do I have to leave it as all text on one line?
Enable TextWrapping="Wrap" and AcceptsReturn="True" on your TextBox.
You might also wish to enable AcceptsTab and SpellCheck.IsEnabled too.
Also, if, like me, you add controls directly in XAML (not using the editor), you might get frustrated that it won't stretch to the available height, even after setting those two properties.
To make the TextBox stretch, set the Height="Auto".
UPDATE:
In retrospect, I think this must have been necessary thanks to a default style for TextBoxes specifying the height to some standard for the application somewhere in the App resources. It may be worthwhile checking this if this helped you.
Here is a sample XAML that will allow TextBox to accept multiline text and it uses its own scrollbars:
<TextBox
Height="200"
Width="500"
TextWrapping="Wrap"
AcceptsReturn="True"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"/>
The only property corresponding in WPF to the
Winforms property: TextBox.Multiline = true
is the WPF property:
TextBox.AcceptsReturn = true
or
<TextBox AcceptsReturn="True" ...... />
All other settings, such as VerticalAlignement, WordWrap etc., only control how the TextBox interacts in the UI but do not affect the Multiline behaviour.
Contrary to #Andre Luus, setting Height="Auto" will not make the TextBox stretch. The solution I found was to set VerticalAlignment="Stretch"
I haven't used WPF that much so the solution to this is probably pretty easy.
In the ide I'm developing it will have multiple controls(text editor) each being hosted in a tab, much like VS does for each source file. When the user clicks new the "host" creates a new EditorWindow(a usercontrol), creates a new tab, and tells the tab to display the EditorWindow it created, and then updates a property called currentWindow (of type EditorWindow) with the one that's currently active. Inside the EditorWindow is the text editor whose name is textEditor(also a property). What I'm trying to do is take this code from the quick start source of the text editor control I'm using
<StackPanel>
<CheckBox Checked="EditiorOptionsChecked" IsChecked="{Binding ElementName=Control, Path=currentWindow.textEditor.IsIndicatorMarginVisible}" Content="Indicator margin visible" />
<CheckBox Checked="EditiorOptionsChecked" IsChecked="{Binding ElementName=Control, Path=currentWindow.textEditor.IsLineNumberMarginVisible}" Content="Line number margin visible" />
<CheckBox Checked="EditiorOptionsChecked" IsChecked="{Binding ElementName=Control, Path=currentWindow.textEditor.IsRulerMarginVisible}" Content="Ruler margin visible (useful for fixed-width fonts only)" />
<CheckBox Checked="EditiorOptionsChecked" IsChecked="{Binding ElementName=Control, Path=currentWindow.textEditor.IsSelectionMarginVisible}" Content="Selection margin visible" />
</StackPanel>
put that in the host controls xaml, and bind the checkboxes to the syntax editor. I've tried a couple different things to no avail. Control is the name of the window hosting all the tabs, and path is obviously supposed to be the property that the checkboxes are bound too. I'm pretty sure the problem is that at initial run-time currentWindow isn't initialized so therefore my bindings aren't ever getting updated, but I'm at a loss as to how to fix this issue. Thanks!
Since you are new to WPF, you may not know that properties have to implement some sort of change notifications in order for bindings to work. For instance, if any of the properties in the the path "currentWindow.textEditor.IsIndicatorMarginVisible" change, you need to inform the binding engine that it has changed. If you implement these properties as DependencyPropertys, the change tracking comes for free. Otherwise, you should implement INotifyPropertyChanged.
I've found that the Snoop utility is the easiest way to do quick binding debugging, you should try using it and see if it tells you anything useful on the bound properties.
I'm looking to display text with the wavey red lines where a word is misspelt, but I only want the text to be selectable, not editable. If I set the TextBox's IsReadOnly property to True or IsEnabled to False, the wavey red lines disappear and I can't get around it by putting something transparent as this will prevent the user being able to select sections of the text.
Is there anyway I can keep the red lines, allow the text to be selectable but prevent the actual text being modified?
Thanks
You could hook up to on the text change event of the text box, and just reject the new text. It would have the same effect of readonly without graying out the textbox or getting rid of the spell checking.
Thanks David. I'm currently looking at 2 possible solutions, yours and the following:
I've created a custom control which is based on the standard TextBox, but effectively has 2 textboxes laid on top of one another in this manor:
<TextBox Name="tbxBack"
Foreground="Transparent"
SpellCheck.IsEnabled="True"
TextWrapping="Wrap"
SnapsToDevicePixels="True"/>
<TextBox Name="tbxFront"
Background="Transparent"
TextWrapping="Wrap"
SnapsToDevicePixels="True"
IsReadOnly="True"/>
I think it's pretty straight forward what's going on here, but I'm concerned about the potential overhead this will cause.
The reason I'm looking into the double TextBox solution is that I'm worried if I try and cancel the event, it could end up with some sort of flashing in the control when the text is changed.
I'm developing a program in WPF (VB) that relies on keyboard navigation only.
In my program, I have a listbox that displays up to 20000 items.
What I want is that when the listbox has keyboard focus, and I move to the bottom item that is visible (using ArrowDown), I want the focus to move to the next item outside the listbox. I'm using PgUp and PgDown to scroll the listbox contents, and text search to jump to items.
Is there a way to detect if the focused/selected item is the last/first visible item in the listbox?
If so, I could just use:
ListBox1.MoveFocus(New TraversalRequest(FocusNavigationDirection.Down))
I'd suggest that you don't do this, the user interface should behave consitesntly with other user interfaces in the operating system.
Your users would be better off if you come up with an alternate user interface that's consistent with how user interfaces behave on your target operating system.
It is a little clear from your explanation but either your looking for:
navigation to move outside of the listbox when the last item is selected.
when navigation is attempted beyond the last item in the list that the navigation pops out of the listbox.
If (1) is your objective there is probably a reasonable solution using triggers and or some custom code handling for events based on the selected item and selected item changed. I would have to agree with Tom if this is the case though and suggest that you do not implement it this way since the last item will never be selectable without focus being programatically removed.
If your instead looking to do (2) then it is my experience that the natural behavior of a ListBox is to move to the next control when the Tab key is pressed and I've tested this for the down arrow key as well and it works the same. When I get to the last item in the list focus pops out of the listbox and to the next control according to it's parent.
UPDATE: I have to withdraw my original comments as the behavior I described above do not describe the default behavior in WPF for a ListBox however it is the behavior you will see the behavior I described above (which I believe is the behavior your looking for) when implementing an ItemsControl and specifying an ItemTemplate. Take a look at the following example.
<ItemsControl ItemsSource="{Binding ElementName=TheWindow, Path=ListOStrings}">
<ItemsControl.Template>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border BorderBrush="Magenta"
BorderThickness="1">
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
By chance, this just happens to have the behavior you described since each item in the list behaves almost like a control placed directly as a peer to all the other controls.
I use an easy trick to move the focus outside Listbox:
I disable the listbox so the focus moves automatically to the next control, then i enable the listbox again :)
Lst.IsEnabled = False
Lst.MoveFocus(New TraversalRequest(FocusNavigationDirection.Next))
Lst.IsEnabled = True