I have a WPF window where I am displaying some locations info. The locations are coming from a BindingList ( AvailableLocations
) and are displayed using DataTemplate
inside a ScrollViewer
. Below is my xaml code.
<Border Margin="0" Background="White">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Title" FontSize="14" FontWeight="Bold" Margin="10"/>
<Button Content="X" HorizontalAlignment="Right" MinWidth="0" Grid.Column="1" Command="{Binding CancelCommand}" Margin="2.5" />
</Grid>
<Border Margin="10,0,10,10" BorderBrush="Black" BorderThickness="0.5" Grid.Row="1" Background="GhostWhite">
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="0,2.5,2.5,2.5" IsTabStop="False" Focusable="False">
<ItemsControl ItemsSource="{Binding AvailableLocations}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Description}" Margin="0, 10" MinWidth="200">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="Border" Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
Background="{TemplateBinding Background}"
BorderBrush="Gray"
BorderThickness="1">
<Label x:Name="Content" Content="{TemplateBinding Content}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGreen" TargetName="Border"/>
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="LightGreen" TargetName="Border"/>
<Setter Property="BorderThickness" Value="2" TargetName="Border"/>
<Setter Property="BorderBrush" Value="DarkGreen" TargetName="Border"/>
<Setter Property="FontWeight" Value="SemiBold" TargetName="Content"/>
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
</Border>
<Button Name="btnCancel" Content="_Cancel" Command="{Binding CancelCommand}" IsCancel="True" Grid.Row="2" Margin="10" HorizontalAlignment="right" MinWidth="70"/>
</Grid>
</Border>
And my ViewModel and and Model are as follows
class Window2ViewModel
{
public BindingList<Location> AvailableLocations { get; private set; }
public Window2ViewModel()
{
IList<Location> locations = new List<Location>()
{
new Location(){Description ="Desc 1"},
new Location(){Description ="Desc 2"},
new Location(){Description ="Desc 3"},
new Location(){Description ="Desc 4"},
new Location(){Description ="Desc 5"},
};
AvailableLocations = new BindingList<Location>(locations);
}
}
public class Location
{
public string Description { get; set; }
public double LocationCD { get; set; }
public string LocationType { get; set; }
public double LocationTypeCd { get; set; }
public string LocationTypeMean { get; set; }
public double OrganizationID { get; set; }
}
I am facing 2 issues here.
IsTabStop="False" Focusable="False"
to the ScrollViewer
but that does not work.FocusManager.FocusedElement="{Binding ElementName=controlName}
. But I don't know how can it be done for items inside DataTemplate
.Hope you folks understand the problems I am facing and any help on this will be highly appreciated.
Thanks in advance
After doing a lots of trial and error I realized that the focus is going to neither the Border
nor the ScrollViewer
elements. The focus actually goes to the ItemsControl
element. So setting the IsTabStop = False
to the ItemsControl
resolved my first issue.
For initial focus to the DataTemplate item, I could not find any direct fixes. But using the following code I was able to bring the focus on the first element inside my DataTemplate.
Loaded += (s, e) =>
{
foreach (var item in itemCtrl.Items)
{
UIElement uiElement =
(UIElement)itemCtrl.ItemContainerGenerator.ContainerFromItem(item);
if (uiElement != null)
{
if (uiElement is ContentPresenter)
{
ContentPresenter c = (uiElement as ContentPresenter);
Button b = c.ContentTemplate.FindName("btn", c) as Button;
Dispatcher.BeginInvoke(new Action(() =>
{
b.Focus();
}), DispatcherPriority.Normal);
return;
}
}
}
};
I am not so sure whether the above can be done directly inside xaml. Hope somebody will find a more appropriate solution. For the time being, the above fix is working for me.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.