ScrollViewer Focus doesn't change to outer control - wpf

I have used ListBox inside TreeView
<TreeView Height="300">
<TreeViewItem Header="Item1"/>
<TreeViewItem Header="Item2">
<ListBox Height="100">
<ListBoxItem Content="Item1"/>
<ListBoxItem Content="Item2"/>
<ListBoxItem Content="Item3"/>
<ListBoxItem Content="Item4"/>
<ListBoxItem Content="Item5"/>
<ListBoxItem Content="Item6"/>
<ListBoxItem Content="Item7"/>
<ListBoxItem Content="Item8"/>
</ListBox>
</TreeViewItem>
<TreeViewItem Header="Item3">
<ListBox Height="100">
<ListBoxItem Content="Item1"/>
<ListBoxItem Content="Item2"/>
<ListBoxItem Content="Item3"/>
<ListBoxItem Content="Item4"/>
<ListBoxItem Content="Item5"/>
<ListBoxItem Content="Item6"/>
<ListBoxItem Content="Item7"/>
<ListBoxItem Content="Item8"/>
</ListBox>
</TreeViewItem>
<TreeViewItem Header="Item4">
<ListBox />
</TreeViewItem>
<TreeViewItem Header="Item5">
<ListBox />
</TreeViewItem>
<TreeViewItem Header="Item6"/>
</TreeView>
When I point the mouse point in ListBox and start scrolling the ListBox get scrolled. When the Scrolling gets end I need to change the focus to TreeView scroll viewer so, that TreeView get scroll. In this code the scrolling doesn't work for TreeView when mouse is inside ListBox.

I need to change the focus to outer control scroll viewer when after ListBox get scrolled
This is not a good description of your problem, but if you are saying that you want to be able to move focus from inside the ListBox to outside the ListBox, then it seems that all you need is to learn how to navigate a ListBox from a keyboard using the arrow keys.
If focus is on a TreeViewItem that has a ListBox in it, then you can press the right arrow key to expand the item and iterate through the ListBoxItems. You can then press the up and down arrow keys to select the previous or next items in the ListBox.
Once you have finished looking through the ListBoxItems, you can then press the left arrow key to navigate back to the TreeViewItem from the ListBox. You will then be able to press the up and down arrow keys to navigate through the TreeViewItems once again.
If that has not helped you with your problem, then please edit your question and add a clear description of your problem.
UPDATE >>>
You can detect when a ListBox has been scrolled to the bottom by handling the ScrollViewer.ScrollChanged event:
<ListBox ItemsSource="{Binding Days}" ScrollViewer.CanContentScroll="False"
ScrollViewer.ScrollChanged="ListBox_ScrollChanged" />
...
private void ListBox_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
ScrollViewer scrollViewer = (ScrollViewer)e.OriginalSource;
if (scrollViewer.VerticalOffset + scrollViewer.ViewportHeight ==
scrollViewer.ExtentHeight)
{
// The ListBox was scrolled to the bottom
}
}
Then, you can focus the next UI element using the TraversalRequest class and the UIElement.MoveFocus method:
TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next);
UIElement focusedElement = Keyboard.FocusedElement as UIElement;
if (focusedElement != null) focusedElement.MoveFocus(request);

Related

WPF: Scrollviewer not limiting content to size of window

I have a treeview with a scrollviewer. When the treeview becomes to full with treenodes i want the scrollbar to show up. But no matter how big the treeview gets it never shows up. The treeview grows outside of window without limiting itself to staying inside window.
The structure is currently:
MainWindow contains a Frame that displays a page, the page contains a usercontrol, the usercontrol contains a treeview.
The usercontrol is set to "stretch", but instead of stretching to fit it's parent (limiting the space and thus making scrollbar appear), it stretches to fit all it's children (and thus stretching outside of screen).
How would i go on about making the "auto" sizing limiting itself to it's parent, instead of making it showing all children?
How i would like it to look/work like
How it actually looks/works like
Code, kinda irrelevant, i just wanna know how i should apply scrollview:
MainWindow:
<Frame Source="View/Pages/StartPage.xaml" x:Name="MainFrame" NavigationUIVisibility="Hidden"/>
</DockPanel>
MainPage:
<Grid>
<Frame Source="ParamFrameV.xaml" x:Name="pageFrame" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
ParamFrameV (the usercontrol):
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" VerticalAlignment="Top" MaxHeight="I WANNA LIMIT HEIGHT SO THAT IT WONT GO OFF SCREEN" Width="283">
<TreeView ItemsSource="{Binding Nodes}" ItemContainerStyle="{StaticResource TreeViewItemExpandedStyle}">
//irrelevant code for this question
</TreeView>
</ScrollViewer>
that works just fine for me:
<Grid>
<ScrollViewer Height="{Binding ElementName=ParentGridName, Path=ActualHeight"}" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" VerticalAlignment="Top" Width="283">
<TreeView Width="50" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<TreeViewItem Header="hi"></TreeViewItem>
<TreeViewItem Header="hi2"></TreeViewItem>
<TreeViewItem Header="hi3"></TreeViewItem>
<TreeViewItem Header="hi4"></TreeViewItem>
<TreeViewItem Header="hi5"></TreeViewItem>
<TreeViewItem Header="hi6"></TreeViewItem>
<TreeViewItem Header="hi7"></TreeViewItem>
<TreeViewItem Header="hi8"></TreeViewItem>
</TreeView>
</ScrollViewer>
</Grid>
Note:
scroling on the treeview itself will not scroll as it will capture your scroll event but i bet there is a way around this

WPF: Clicking on a DataGrid Row inside a TreeView does not trigger TreeView.SelectedItemChanged

I am new to WPF, and suffering with an existing code.
We have a tree, which has many branches/leaves. In one branch we have a DataGrid.
If we click on the empty area of the grid (where no rows are), then TreeView.SelectedItemChanged called properly. In our case, SelectedItem = 'SelectedGridBorder' (see XAML below)
But if we click on a row/cell of the grid, row gets focused, but TreeView.SelectedItemChanged is NOT called.
So TreeView.SelectedItem is still the previously selected item.
Is is possible to achieve this (according to me) logical behavior, so when clicking on a row, TreeView.SelectedItemChanged should be called automatically, and TreeView.SelectedItem should be 'SelectedGridBorder', just like clicking on the grid area where no rows are.
Why is it different for 'SelectedItemChanged' to click on a grid row, or click on a grid where no rows are?
Thanks.
XAML:
<TreeView x:Name="CalculationDataTree" .....>
<Cinch:EventCommander.Mappings>
<Cinch:CommandEvent
Command="{Binding Path=DataContext.SelectionChangeCommand ....
Event="SelectedItemChanged"
Cinch:CommandEvent.CommandParameter="{Binding ElementName=CalculationDataTree,Path=SelectedItem}"/>
...
<TreeViewItem x:Name="Params" ...>
<TreeViewItem.Header>
<TextBlock>Parameters</TextBlock>
</TreeViewItem.Header>
<TreeViewItem x:Name="Dates" Margin="0,6,0,0">
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="4,10">Date(s)</TextBlock>
<ContentControl Margin="4,6" Content="{Binding}" ContentTemplate="{StaticResource OwnEditorTemplate}" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
<Border Name="SelectedGridBorder" ... >
<StackPanel Orientation="Vertical">
<TextBlock Margin="4,10">Other parameters</TextBlock>
<StackPanel Orientation="Horizontal">
<DockPanel>
<dg:DataGrid Height="300" Width="600" Name="dataGrid" ....>
<dg:DataGrid.Columns>
...
</dg:DataGrid.Columns>
The answer to
Why is it different for 'SelectedItemChanged' to click on a grid row, or click on a grid where no rows are?
MouseDown is a bubbling event. What's happening is the TextBox of your DataGrid marked the event as handled so it never reached TreeViewItem (WPF creates the TreeViewItem automatically even though you didn't specifically include it in your markup). If you clicked on a Header, or RowSelector, they would not mark the event as handled.
To get the behavior you were expecting
//WPF creates the TreeViewItem automatically if you didn't include it
<TreeViewItem PreviewMouseDown="TreeviewItem_PreviewMouseDown">
<Border Name="SelectedGridBorder" ... >
<StackPanel Orientation="Vertical">
<TextBlock Margin="4,10">Other parameters</TextBlock>
<StackPanel Orientation="Horizontal">
The Handler
private void TreeviewItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var treeViewItem = sender as TreeViewItem;
treeViewItem.IsSelected = true;
}

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>

Automatic ListBox Selection/SelectedItem/SelectedIndex changed while moving mouse out of ListBox

Have a ListBox with couple of items. Select any item (say the v.first item) and keep try to Drag it in empty area (Outside of listbox), ListBox selection is getting changed. Albeit I'm moving mouse in area out of ListBox.
I want selection change only when i move mouse within the ListBox. Or completely disable the selection change while mouse move (Dragged). Here is the snapshot of a small poc.
<Grid>
<ListBox HorizontalAlignment="Left" Margin="111,49,0,180" Name="listBox1" Width="154">
<ListBoxItem BorderThickness="2" Height="50" Width="Auto" Name="heig" BorderBrush="Chocolate">Rohit Item 1</ListBoxItem>
<ListBoxItem Height="50" BorderThickness="2" BorderBrush="Blue" >Vivek</ListBoxItem>
<ListBoxItem Height="50" BorderBrush="Cyan" BorderThickness="2" >Gaurav</ListBoxItem>
<ListBoxItem Name="height" Height="50" BorderBrush="CornflowerBlue" BorderThickness="2" >Asit Item 2</ListBoxItem>
</ListBox>
</Grid>`
You should capture the mouse while dragging, preventing other input from happening while you are dragging. This is done when drag starts:
Mouse.Capture(listBox);
I just stumbled over this topic again and I have to tell you that there is no perfect solution but a, imho, good workaround. You can find it here

How can I underline an ListBoxItem in WPF?

How can I underline an ListBoxItem in WPF? I'm using the following but the underline does not appear.
<DataTemplate x:Key="Phrase_List">
<ListBoxItem IsSelected="{Binding IsDefault}">
<TextBlock Text="{Binding Path=Phrase}" Tag="{Binding Path=ID}" TextDecorations="Underline" />
</ListBoxItem>
</DataTemplate>
I don't know what code you are trying to use. Please try to complete your question. I've used the following code to underline the 'World' item in my little ListBox.
<ListBox>
<ListBoxItem>Hello</ListBoxItem>
<ListBoxItem>
<Underline>World</Underline>
</ListBoxItem>
</ListBox>
You can use a textblock, and set the textdecorations property to underline. Remember the contents of a ListBoxItem can be things other than text, hence why it's not a simple case of setting some property on the ListBoxItem.
You will need to create an item template that displays your text in a TextBlock control. On the TextBlock, set the TextDecorations property (which is a collection) to contain 'Underline'.
In XAML:
<ListBox Name="lst">
<ListBoxItem Content="item1" />
<ListBoxItem Content="item2" FontStyle="Italic" FontWeight="Normal" />
</ListBox>
In C#:
lst.Items.Clear();
lst.Items.Add(new ListBoxItem { Content = "item 1" });
lst.Items.Add(new ListBoxItem { Content = "item 2" });
lst.Items.Add(new ListBoxItem { Content = "item 3" });
ListBoxItem l = (ListBoxItem)lstItems.Items[2];
li.SetValue(TextElement.FontStyleProperty, FontStyles.Italic);

Resources