C# WPF: How to keep keyboard focus in main window? - c#

I am working on a simple image viewer.
It contains a viewbox which shows the current image.
Below I added a thumbnail strip created by a wrappanel inside a listview which contains the thumbnails in viewboxes again.
I am able to switch the current image by key events (code excample "space", in real space and arrow keys). By clicking in one of the thumbs it is also possible to update the current image.
Unfortunately, whenever I select a thumb in the Listview, the Mainwindow looses keyboard focus and I am not able to use the keys anymore to switch the images.
I tried all solutions found in the net, but nothing really works, now I am completely lost.
Any ideas.
...
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:MainWindow.command1}" CanExecute="command1CanExecute" Executed="handlecommand1"/>
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="{x:Static local:MainWindow.command1}" Key="Space" />
</Window.InputBindings>
...
<DockPanel>
<ListView x:Name="ThumbSlider" ... Some Settings ... Focusable="False" MouseUp="ListboxMouseUp">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate>
<Viewbox ... Some Settings ... ScrollViewer.VerticalScrollBarVisibility="Disabled" Height="120" Width="120" Focusable="False">
<Image Source="{Binding Path=ThumbImage}"></Image>
</Viewbox>
</DataTemplate>
</ListView.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListView>
<Viewbox x:Name="CurrentImageBox" DockPanel.Dock="Top" >
<Image Source="{Binding Path=CurrentImage}"/>
</Viewbox>
...
</DockPanel>

Related

How to hide a child element from Xceed Magnifier?

I am able to zoom using Magnifier (Xceed's control toolkit).
I have multiple controls in Grid that I want to get rid off imageEditor and ListBox controls from Magnifying Glass when it gets zoom.
My code is below.
<Grid>
<wpfMagnifier:MagnifierManager.Magnifier>
<wpfMagnifier:Magnifier x:Name="magnifiyingGlass" Visibility="Hidden"
FrameType="Circle" Radius="240" ZoomFactor=".4" BorderBrush="#9cc63e" BorderThickness="9">
</wpfMagnifier:Magnifier>
</wpfMagnifier:MagnifierManager.Magnifier>
<Image x:Name="cvT" >
</Image>
<imageEditor:UserControl1 x:Name="UserControlID1" Points="{Binding Points}" IsClosedCurve="{Binding IsClosedCurve}" />
<ListBox ItemsSource="{Binding Points}" ItemContainerStyle="{StaticResource PointListBoxItemStyle}" x:Name="ItemsContainer"
PreviewMouseLeftButtonDown="ItemsContainer_PreviewMouseLeftButtonDown" MouseMove="ItemsContainer_MouseMove" PreviewMouseLeftButtonUp="ItemsContainer_PreviewMouseLeftButtonUp">
<ListBox.Template>
<ControlTemplate>
<Canvas IsItemsHost="True"/>
</ControlTemplate>
</ListBox.Template>
</ListBox>
</Grid>
How to implement it?

WPF Listbox items with name on mouseover or active

I've tried several different solutions to this, but can't land on one that meets all of my needs.
We have an observable collection of objects that each have a status and a name. It's a sort of task-list of running items. To display this list in WPF, we have some code that represents each item as an ellipse with some colors and animations.
The problem is that we want to display the name of the item as a 'popup' both on mouseover, or when the task is in a given state.
Attempt #1
My first attempt implemented this as a Datatemplate (to be used as an ItemTemplate) with an actual WPF Popup. I implemented two datatriggers - one for mouseover and one for task state. I positioned the popup based on my ellipse and everything was great. However, moving the window or switching to a different window left the popup on top of everything.
Attempt #2
Instead of using the popup I used a textbox in a canvas. This works great until the Datatemplate is used in the Listbox. The item host (stackpanel) ends up clipping the string.
Here's example code:
<DataTemplate x:Key="EllipseTemplate">
<Grid Height="40" Width="40">
<Canvas Name="PopupCanvas" HorizontalAlignment="Center" Width="500">
<TextBlock Name="PopupName"
Width="{Binding ElementName=PopupCanvas, Path=ActualWidth}"
Text="{Binding}"
Background="Transparent"
FontSize="16" HorizontalAlignment="Center" TextAlignment="Center" FontWeight="Bold"
Canvas.Top="-25"
Visibility="Collapsed"
/>
</Canvas>
<Ellipse x:Name="Ellipse" Height="25" Width="25" Margin="0"
HorizontalAlignment="Center" VerticalAlignment="Center"
Fill="Green"
RenderTransformOrigin="0.5, 0.5" StrokeThickness="0.5" Stroke="Black">
</Ellipse>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource TemplatedParent}}" Value="True">
<Setter TargetName="PopupName" Property="Visibility" Value="Visible" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<Grid Name="Test" Background="LightGoldenrodYellow" ClipToBounds="False" Margin="50">
<ListBox Name="OverlayTest"
Background="CornflowerBlue"
BorderThickness="0"
VerticalAlignment="Center"
Margin="10"
ClipToBounds="False"
ItemTemplate="{StaticResource EllipseTemplate}">
<sys:String>Very long string that will get clipped</sys:String>
<sys:String>Two</sys:String>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" Margin="10,50,10,50" ClipToBounds="False"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
Attempt #3
I moved my canvas/textbox outside of the datatemplate and create a grid to put it above the listbox of ellipses. This works from a layout perspective, but creates a big mess in terms of checking for mouseover and centering the textbox on the control that's active/hovered.
So that leaves me without an implementation that works the way I want. Anyone have any suggestions?
Ok here I have another idea. I had problem with the ListBox before. Try replacing the ListBox with an ItemsControl.
Attempt #2 sounds like is working fine. You should be able to solve the issue of the clipping using one of these solutions (or all of them):
Set the ClipToBounds property of the ListBox to false
Set the ClipToBounds property of the Stackpanel to false

How to display listbox items in column view in WPF c#

Am using listbox control in WPF its display listbox item in row wise but I want to display in column wise ( Something like bootstrap grid)
XMAL
<ListBox x:Name="lb_items">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10 0 0 0">
<Image Source="{Binding ImageSource}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Am binding Listbox from code behind
lb_items.ItemsSource = modules.ToList();
Try this one.
<ListBox x:Name="lb_items">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10 0 0 0">
<Image Source="{Binding ImageSource}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ListBox has property called ItemsPanel, which determines how items are rendered.
Somewhere in application resource create different ItemsPanelTemplate, so you can easily reuse it:
<ItemsPanelTemplate x:Key="WrapPanelTemplate">
<WrapPanel />
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="HorizontalStackPanelTemplate">
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
then you can easily use it:
<ListBox ItemsPanel="{StaticResource HorizontalStackPanelTemplate}">...
<ItemControl ItemsPanel="{StaticResource WrapPanelTemplate}">...
always put such assets into application resources in order to make the code for your views clean and readable.
Extra Tip:
Here is animated WrapPanel, that animates items, when you resize window or an item is inserted to the list:
<ItemsPanelTemplate x:Key="FluidWrapPanel">
<WrapPanel>
<i:Interaction.Behaviors>
<ei:FluidMoveBehavior AppliesTo="Children" Duration="0:0:0.5">
<ei:FluidMoveBehavior.EaseY>
<SineEase EasingMode="EaseInOut" />
</ei:FluidMoveBehavior.EaseY>
<ei:FluidMoveBehavior.EaseX>
<CubicEase EasingMode="EaseInOut" />
</ei:FluidMoveBehavior.EaseX>
</ei:FluidMoveBehavior>
</i:Interaction.Behaviors>
</WrapPanel>
</ItemsPanelTemplate>
dont forget to include these xml namespaces:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

Change ItemTemplate

I have the following 2 DataTemplates:
<DataTemplate x:Key="ItemPhoto">
<StackPanel>
<Image Source="{Binding Thumbail}" Height="80" Width="80" HorizontalAlignment="Stretch" Stretch="UniformToFill"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ItemAlbum">
<StackPanel>
<Image Source="{Binding Thumbail}" Height="100" Width="100" HorizontalAlignment="Stretch" Stretch="UniformToFill"/>
</StackPanel>
</DataTemplate>
And 1 GridView
<GridView Grid.Row="1" Name="lstFlickrControl"
SelectionMode="Multiple"
ItemTemplate="{StaticResource ItemPhoto}"
ItemClick="lstFlickrControl_ItemClick" Holding="lstFlickrControl_Holding">
<GridView.ItemContainerStyle>
<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="2"/>
</Style>
</GridView.ItemContainerStyle>
</GridView>
I want that when I click the photo menu GridView it should load the ItemPhoto DataTemple but when I click the albums menu GridView it should load the ItemAlbums DataTemple. Can someone please make some suggestions?
Try this way, for example upon albums menu clicked change ItemTemplate to use ItemAlbum DataTemplate :
lstFlickrControl.ItemTemplate = (DataTemplate)this.Resources["ItemAlbum"];
note : you may need to change this in above sample to whatever UI control where you define those DataTemplates

How to set animations/transitions when adding elements to a ListViews?

I have got a ListView wich I added Elements by binding. The ListView looks like:
<ListView
x:Name="ListView"
Height="auto"
Width="350"
ItemsSource="{Binding}"
Padding="0,0,-20,0"
Grid.Row="1"
Grid.Column="0"
Background="#EFEFEF"
ItemContainerStyle="{StaticResource ListViewStyle}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Height="50" VerticalAlignment="Top" Margin="0,0,0,0"
<TextBlock Text="{Binding name} TextWrapping="NoWrap"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
With this basic setup there is already an animation when a element is bonded to the underlying List. Strangely to different animations are used. The first element slides in from the right and all other elements popup. I’m searching for a way to animate all added elements the same way (e.g. slide in from the right). I have been locking into the auto generated (by Blend) ListViewStyle for hours now but couldn't find something. Later I found out that it is possible to add this property inside the style:
<Style x:Key="ListViewStyle" TargetType="ListViewItem">
<Setter Property="Transitions">
<Setter.Value>
<TransitionCollection>
<EntranceThemeTransition FromHorizontalOffset="400" />
<PopupThemeTransition FromHorizontalOffset="400"/>
</TransitionCollection>
</Setter.Value>
</Setter>
...
</Style>
The EntranceThemeTransition and PopupThemeTransition seems to be the right properties because they change the behavior of the animation. But I don't know how to use them or how to disable one. How can I get just one animation (slide in from the right) to the ListView?
This should work:
<ListView
x:Name="lv">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel>
<VirtualizingStackPanel.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition
FromHorizontalOffset="400" />
</TransitionCollection>
</VirtualizingStackPanel.ChildrenTransitions>
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
*Update:
You can also use ListView.ItemContainerTransitions to define these transitions.

Categories