Prevent focus/tabbing into non visible element in UI - wpf

For example, I have Grid with two rows and GridSplitter between them. When one the rows is not visible in UI (eg. splitter is all the way on top; real case scenario is more complicated with nested controls) elements are still reachable via tab key - I would like to prevent that.
I am aware of IsVisible property of FrameworkElement (is true even for such elements) and/or IsEnabled/IsTabStop and KeyboardNavigation class in general, but none of them solves my problem. My elements are usable etc., just not currently visible in UI because of grid splitter. Basically only framework elements which can be reached by mouse should also participate in tab key functionality.
Simplest case when it can be reproduced is following content of main window (move splitter to upper most position).
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="10"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" KeyboardNavigation.TabNavigation="Once"/>
<GridSplitter Height="10" Grid.Row="1" KeyboardNavigation.TabNavigation="Once" HorizontalAlignment="Stretch"/>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox x:Name="PART_Problem" Grid.Row="0" KeyboardNavigation.TabNavigation="Once"/>
<TextBox Grid.Row="1" KeyboardNavigation.TabNavigation="Once"/>
</Grid>
</Grid>
Result should be that non-visible elements should be skipped and next visible element should be focused instead. This functionality should be compatible with KeyboardNavigation.ControlTabNavigation.
Edit 1: changed sample a little in order to show, that PART_Problem keeps ActualHeight to some non-zero value, which eliminates solutions based on size changes.

Try setting the property Focusable="False" in XAML

Related

WPF button position dependent on another element

I would like to place my button always on the middle of the bottom frame of ScrollViewer. I am going to change both the size of window, and a size of ScrollViewer, but I want my button to be always as on the pictures.
Owing to the fact that i am following MVVM, I have just xaml. Basically, I would like to bind (live) the button top position from the pattern:
button.top = (scrollViewer.top + scrollViewer.height) - button.height/2
I would be grateful for your suggestions.
[EDIT] I forgot to add that all other controls are in grid rows and columns.
You can try to use Grid to achieve that. If you need to change the ScrollViewer size, just change ScrollGrid Grid size instead. To overlap bottom or top content, you can use negative margins for the button.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Border Background="Red"/>
<Border Background="Red" Grid.Row="2"/>
<Grid x:Name="ScrollGrid" Grid.Row="1">
<ScrollViewer></ScrollViewer>
<Button Width="100" Height="100" VerticalAlignment="Bottom" HorizontalAlignment="Center"/>
</Grid>
</Grid>

How to customize the visible area of the scroll viewer's content

The ScrollViewer's default behavior is, that the content stops on the bottom of the ScrollViewer's view port:
I would like to change the behavior, so that the content can be scrolled to the top of the scroll ScrollViewer's view port:
a) Is it possible to configure the existing scroll viewer that way?
b) If not, what is the best way to achieve that behavior?
Embed the scrollable content in a Grid with 3 rows. The scrollable content occupies the second row. The other two have the same Height of the ScrollViewer:
<ScrollViewer Height="50">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<YourScrollableContent Grid.Row="1"/>
</Grid>
</ScrollViewer>
I've no way to test it in order to see if this code is perfect, but I'm sure this can be a way :)
Maybe you can bind the Height of the 2 rows with the Height of the ScrollViewer:
<RowDefinition Height="{Binding Path=Height,
RelativeSource={RelativeSource AncestorType=ScrollViewer}}"/>

Vertical sizing in WPF trouble

I'm having trouble vertically sizing the CheckListBox control from https://wpftoolkit.codeplex.com/. I'm a week-old newbie in WPF, so this is probably a general issue with (vertical) sizing.
Given my grid, I want the first 5 rows to size whatever size, they need to be, and in my viewport, I want the CheckListBox control in row 6 to simply fill the remaining space vertically.
My problem is, that when I fill the CheckListBox with a lot of elements, the control just expands / overflows the viewport. What I want it to do, is to assume the height of the remaining space vertically, which will make it display an inner scrollbar.
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0">Some title</Label>
<RadioButton Grid.Row="1" GroupName="NameSortRadioButtonGroup">Firstname Lastname</RadioButton>
<RadioButton Grid.Row="2" GroupName="NameSortRadioButtonGroup">Lastname, Firstname</RadioButton>
<TextBox Grid.Row="3" Margin="0,5" />
<Label Grid.Row="4" Content="{Binding ElementName=MyCheckListBox, Path=SelectedItems.Count}" />
<xctk:CheckListBox
Grid.Row="5"
Name="MyCheckListBox"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
Height="Auto"
/>
</Grid>
I have left out some parent elements to simplify. The Grid is in a grid, that's in a canvas, that's in a grid, and this outer grid is direct child of the Window element.
I have tried wrapping the CheckListBox control in a StackPanel with Height="Auto" (to eliminate the possibility of a bug in the CheckListBox) and also here to set the height of the CheckListBox using
Height="{Binding ElementName=CheckListBoxStackPanelWrapper, Path=ActualHeight}"
I also initially tried to do the whole thing with first a StackPanel and later a DockPanel instead of the Grid control.
In all cases, the CheckListBox just flows out of the window/viewport. If I give it an explicit height, it behaves correctly, but I obviously want my window to be resizable.
What shall I do?
To sum up comments because your outer control is a Canvas which does not restrict its child elements From MSDN:
Child elements of a Canvas are always given the full size that they desire
which means that Grid will be given as much space as it require. One solution is to remove the Canvas part or restrict the size size of Grid or expanding row

DataGrid Sizing Issue

I am trying to load data into a datagrid but I am having a nightmare with sizes. My datagrid seem to take as much space as it wants. I want it to load into the current size and display scroll bars if needed.
Could someone explain how the sizing works thank you.
Example:
<Grid Name="MainUI" Height="Auto" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid Name="MainGrid" Grid.Row="1" VerticalAlignment="Top" Height="Auto" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<TabControl TabStripPlacement="Bottom" Name="Main_Tab" VerticalAlignment="Top" Visibility="Visible" />
</Grid>
</Grid>
Within the tab control I create a datagrid on a new tab item in the code behind when this happens, the datagrid takes as much room as possible.
The datagrid of itemTab has no sizing on it when I load it.
Thanks
Setting the Height/Width to Auto means the control should take up as much space as it needs. This means if the control needs more space than is available in the UI, it's allowed to stretch the parent control and take up however much space it wants.
Remove the Height="Auto" and Width="Auto" to fix the issue
If it is still giving you trouble, try setting HorizontalAlignment and VerticalAlignment to Stretch. This will make the control will grow or shrink itself to take up all space available to it, however it won't expand the container it is in to take up additional space.

How to access actual Height of Elements with Height=Auto

I have a situation like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="560"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <!-- status infos & content start -->
<RowDefinition Height="Auto" /> <!-- status infos -->
<RowDefinition Height="Auto" /> <!-- status infos -->
<RowDefinition Height="Auto" /> <!-- status infos -->
<RowDefinition Height="*"/> <!-- content ends -->
</Grid.RowDefinitions>
<!-- image a list of custom controls directed to the first or second column on all rows here -->
<SomeCustomControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Grid.RowSpan="2" />
</Grid>
As you can see I have 2 Columns, the right one is more or less reserved for status information, the left for content. "SomeCustomControl" contains a control so wide it needs to be set to ColumnSpan="2". Notice there are still the status control in the right column. In SomeCustomControl I have something like this:
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
[...]
<RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <!-- problem control here -->
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- a list of Controls limited to the first column -->
<ProblemControl Grid.Column="0" Grid.ColumnSpan="2" />
</Grid>
Now, the first Rows of SomeCustomControl contain controls limited to the first column, then there is a row that contains my ProblemControl. The Height of the status controls is not predetermined and depends on the shown status information. The controls in SomeCustomControl that are limited to the first column also have different heights, that are currently determined automatically through the content.
I now have the problem that ProblemControl overlaps with some of my status controls. I tried to calculate the height of my status controls and the limited controls in SomeCustomControl, but as all controls are sized dynamically I can't seem to get correct Heights. The Height of the RowDefinitions all contains Heights of type Auto and value 1, the Heights of the concrete Controls seems to be NaN.
Any ideas as to how I can calc the heights or prevent the overlapings in other ways.
I've encountered somewhat of the same problem, but came across the solution recently. The reason why you can't access the width and height properties of a control with width or height set to Auto is that the run time system is querying for the property values before they've been set. The properties ActualWidth and ActualHeight claim to get the rendered height of controls so in theory, you'd think you could simply wait until the SL application had finished loading and then perform your query, since the controls would be rendered by then and therefore, the ActualHeight/ActualWidth values should be set.
Sadly, this isn't the case either. There doesn't seem to be any guarantee when those values are set, so the workaround I used is to hook into the SizeChanged-event of the control whose values I want. SizeChanged is triggered whenever the width and height properties of a control are changed, so if I handle that event, I am guaranteed that the values are set to something other than NaN.
Do whatever logic you need to perform in a handler for that event, and you'll find the values are set.
Have you tried with ActualHeight property on control ?
You ought to be able to solve this with proper use of the Grid and some panels (DockPanel and StackPanel can be quite useful). You may also need the HorizontalAlignment or VerticalAlignment properties set to Stretch on some controls.
Your example doesn't have enough in it for us to duplicate your problem or to know that we've addressed it correctly. If you'd like more specific help, please expand the example so we can run it and see your issue.

Resources