Tabbing User Control In Listbox DataTemplate - wpf

I have a User Control in a ListBox and when I use the tab key to focus I'd like to get the focus on the TextBox in my Control instead of the Custom Control. How can I do it?
I simplified the code because In my control I have other UI Elements.
User Control Code:
<Grid>
<TextBox Name="txtFreeTextDescription" Style="{StaticResource TextBoxStyleLargeDynamic}" Text="{Binding Description, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
</Grid>
ListBox Code:
<ListBox Name="lsbItems" DataContext="{Binding}" KeyboardNavigation.TabNavigation="Local">
<ListBox.ItemTemplate>
<DataTemplate>
<local:SectionDynamicItem x:Name="ucSectionDynamicItem" Description="{Binding SectionItem.Description}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

This works for me....
<ListBox ItemsSource="{Binding EmployeeList}"
KeyboardNavigation.TabNavigation="Continue">
<ItemsControl.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Focusable" Value="False"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="5" Focusable="False">
<TextBox Text="{Binding Name}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>

Check below link.
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/98d8423c-9719-4291-94e2-c5bf3d80cd46/
Thanks
Rajnikant

Related

Change displayed text in XAML Combobox multi selection

I have the following code to allow users to select multiple items from a combobox. However when they click one item, it makes this the displayed text when combobox closes. Can I change the displayed text to something that isnt just the item selected. For example if the users select items A,B and D, I want the text part of the combobox to show "A, B, D"
<ComboBox ItemsSource="{Binding ListOfItems}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Width="20" />
<TextBlock Text="{Binding DisplayName}" Width="110" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Thanks
You could use a ContentControl with a Style that changes the ContentTemplate property for the selected item. The following sample markup should give you the idea.
<ComboBox ItemsSource="{Binding ListOfItems}">
<ComboBox.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate">
<Setter.Value>
<!-- the template for the items in the dropdown list -->
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Width="20" />
<TextBlock Text="{Binding DisplayName}" Width="110" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ComboBoxItem}}" Value="{x:Null}">
<Setter Property="ContentTemplate">
<Setter.Value>
<!-- the template for the selected item-->
<DataTemplate>
<ItemsControl ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource AncestorType=ComboBox}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" Margin="0 0 5 0"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Please refer to the following similar question for more information.
Can I use a different Template for the selected item in a WPF ComboBox than for the items in the dropdown part?

ScrollViewer content is scrolling over other parts of window

I have the following as part of my XAML:
<DockPanel>
<ToolBar Name="toolbar1" DockPanel.Dock="Top" Height="41" Background="#FFA5D95A">
//other controls
</ToolBar>
<ScrollViewer>
<ListBox Name="listBox1" ItemsSource="{Binding ElementName=This, Path=Items}"
ItemTemplateSelector="{StaticResource entryItemTemplateSelector}">
<ListBox.Template>
<ControlTemplate>
<WrapPanel IsItemsHost="True" />
</ControlTemplate>
</ListBox.Template>
</ListBox>
</ScrollViewer>
</DockPanel>
I want the scrool bar to move the items in the ListBox just to the top of the WrapPanel, and then to stop showing them when they get to the top; in stead, these items scroll into the ToolBar at the top.
What am I doing wrong?
Note: Haing been asked, here are the DataTemplates I currently have; EntryItemHost is a type derived from WindowsFormsHost.
<DataTemplate x:Key="folderTemplate">
<my:EntryItemHost Item="{Binding}"
Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:MainWindow, AncestorLevel=1}, Path=Background}"
DoubleClick="FolderDoubleClick" />
</DataTemplate>
<DataTemplate x:Key="imageTemplate">
<my:EntryItemHost Item="{Binding}"
Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:MainWindow, AncestorLevel=1}, Path=Background}" />
</DataTemplate>
Instead of setting ListBox Template set the ItemsPanel and remove the ScrollViewer
sample
<DockPanel>
<ToolBar Name="toolbar1"
DockPanel.Dock="Top"
Height="41"
Background="#FFA5D95A">
//other controls
</ToolBar>
<ListBox Name="listBox1" ItemsSource="{Binding ElementName=This, Path=Items}"
ItemTemplateSelector="{StaticResource entryItemTemplateSelector}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType=ContentPresenter}}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</DockPanel>
notice that I have replaced the template with ItemsPanel and restricted the width to the listbox
I made this based on the assumptions, let me know is this not what you are looking for

Button in ListBox item's ItemsControl doesn't fire in WPF XAML

I've got the following setup for my ListBox in wpf:
ListBox with as ItemsPanel a StackPanel (orientation horizontal)
ItemTemplate of ListBox is a Grid with a TextBox and an ItemsControl
the Items control contains buttons with as ItemPanel a WrapPanel.
Somehow when I click on one of the buttons in the ItemsPanel, the ICommand wont fire in the ViewModel class which is bound to the View.xaml.
It looks like I'm selecting the ListBox item and not the item within the ItemsControl.
Here's the xaml code
<ListBox
Background="Transparent"
ItemTemplate="{StaticResource ProductGroupTemplate}"
FocusVisualStyle="{x:Null}"
VerticalContentAlignment="Top"
ItemsSource="{Binding NodeHeaders}"
Grid.Row="1"
Grid.ColumnSpan="3"
Grid.Column="0"
Grid.RowSpan="2"
SelectedItem="{Binding CurrentItem}"
BorderBrush="Transparent"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
Margin="30,0,55,0"
VerticalAlignment="Top">
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding HasParent}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
And the DataTemplate
<DataTemplate x:Key="ProductGroupTemplate">
<Grid Margin="0,0,20,0">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Description}" FontSize="20" Grid.Row="0" Grid.Column="0" Foreground="{StaticResource DefaultLabelColor}" />
<ItemsControl ItemsSource="{Binding Nodes}" Grid.Row="1" Grid.Column="0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Text="{Binding Description}" Height="75" Width="150" Padding="5" Margin="5" Background="{StaticResource SalesItemsBackground}"
Foreground="{StaticResource SalesItemsForeground}" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Left" Command="{Binding RelativeSource=
{RelativeSource FindAncestor,
AncestorType={x:Type ContentControl}},
Path=DataContext.Select}" CommandParameter="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
If you have a view model that declares an ICommand instance and is set as the DataContext of a view (UserControl, or Window), then you can use that property to access your ICommand instance. From the Button in your DataTemplate, you can use this RelativeSource Binding:
<Button Text="{Binding Description}" Height="75" Width="150" Padding="5" Margin="5"
Background="{StaticResource SalesItemsBackground}" TextAlignment="Left"
Foreground="{StaticResource SalesItemsForeground}" HorizontalAlignment="Center"
VerticalAlignment="Center" Command="{Binding DataContext.Select, RelativeSource={
RelativeSource AncestorType={x:Type YourViewsPrefix:YourView}}}"
CommandParameter="{Binding}"/>
That's because your data template's DataContext is set to an item from the listbox. If you have List<Person> bound to your list box every list box item's DataContext would be a Person which is why you can write something like "{Binding Description}". You have two ways to execute a command from DataTemplate one of them is the one that "Sheridan" told you. As an alternative you could set your element's DataContext to your parent View or ViewModel.
<DataTemplate>
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type View/ViewModel}}">
</Grid>
</DataTemplate>

Dependency Property of Style type

I am wanting to expose a Style as a dependency property. Basically there is a rectangle indicator in the middle and the using control is going to expose a style dependency property for containing controls to set. It would allow those containing controls to provide a style for coloring based on their own knowledge of their items.
<ItemsControl ItemsSource="{Binding Rows}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding RowName}"/>
<ItemsControl ItemsSource="{Binding Statuses}">
<Rectangle Style="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}, Path=RectangleStyle}"/>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The dependency property in the code-behind of the custom control.
public Style RectangleStyle
{
get { return (Style)GetValue(RectangleStyleProperty); }
set { SetValue(RectangleStyleProperty, value); }
}
public static readonly DependencyProperty RectangleStyleProperty =
DependencyProperty.Register("RectangleStyle", typeof(Style), typeof(MyControl), new PropertyMetadata(null));
This would then be used like:
<MyControl>
<MyControl.RectangleStyle>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Red"/>
</Style>
</MyControl.RectangleStyle>
</MyControl>
This is not working at all and I'm not sure if my approach is even correct.
Stupid syntax error. I needed to set the ItemsTemplate for the Inner ItemsControl. I was setting the content of the ItemsControl to be the Rectangle.
<ItemsControl ItemsSource="{Binding Rows}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding RowName}"/>
<ItemsControl ItemsSource="{Binding Statuses}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Style="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}, Path=RectangleStyle}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Styling ListView.GroupStyle with a WrapPanel

Okay, here is my pretty simple problem.
I have a ListView that I styled so as to make it look like the Windows Explorer.
Now, I'd like to group the items inside. Therefore, I defined a GroupStyle with an Expander to group it. The grouping is now fine.
What I don't like is that now, my ListView displays each group on a separate line, while I'd like to have some expander-wrapping in order to display many groups on the same line.
An image is better than some text I guess.
Here is what I have:
Here is what I want:
I cannot find which property should I have to style in order to make the GroupItems fit in a WrapPanel, just like I did for the items.
Here is my ListView style:
<ResourceDictionary>
<!-- Explorer-style layout-->
<DataTemplate x:Key="ExplorerView">
<StackPanel Orientation="Horizontal" Height="Auto" Width="150">
<Image Source="{Binding Path=Value.AppConfig.Appli.AppType, Converter={StaticResource TypeToIconConverter}}" Margin="5"
Height="50" Width="50"/>
<StackPanel VerticalAlignment="Center" Width="90">
<TextBlock Text="{Binding Path=Value.AppConfig.Appli.AppName}"
FontSize="13" HorizontalAlignment="Left" TextWrapping="WrapWithOverflow"
Margin="0,0,0,1" />
<TextBlock Text="{Binding Path=Value.AppConfig.Appli.AppType}" FontSize="9"
HorizontalAlignment="Left" Margin="0,0,0,1" />
</StackPanel>
</StackPanel>
</DataTemplate>
<!-- Group header style-->
<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander x:Name="exp" IsExpanded="True" Width="310"
BorderBrush="CornflowerBlue">
<Expander.Header>
<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="CornflowerBlue" x:Name="expContent"
Width="{Binding RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType={x:Type Expander}},
Path=Width}"
Height="{Binding RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType={x:Type ToggleButton}},
Path=ActualHeight}">
<CheckBox IsChecked="False" DockPanel.Dock="Right"/>
<TextBlock Text="{Binding Path=Name}" Foreground="White"
FontWeight="Bold" HorizontalAlignment="Center" />
</DockPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
<!-- (...) -->
<ListView ItemsSource="{Binding GroupedConfig, Mode=TwoWay}"
ItemTemplate="{StaticResource ExplorerView}">
<ListView.ItemsPanel>
<ItemsPanelTemplate >
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource
AncestorType=Expander}}"
ItemWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
ItemHeight="{Binding (ListView.View).ItemHeight,
RelativeSource={RelativeSource AncestorType=ListView}}" />
<!--MinWidth="{Binding ItemWidth,
RelativeSource={RelativeSource Self}}"-->
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}" />
</ListView.GroupStyle>
</ListView>
Any ideas?
I'm trying to insert some appropriate Setter in the style defined for GroupItem, but I'm starting to think that this is not the right way to do.
Thanks!
I finally found the right property to edit after many tries.
I guess it could be useful to post it here if anybody would need to do something with the same behavior:
So we actually have a property Panel in the GroupStyle in which we can add this so needed WrapPanel :
<ListView.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<WrapPanel Width="800" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ListView.GroupStyle>
In case anyone is here like I am trying to make a the ListBox Items Wrap but based on an unknown amount of items so you cannot set a Width like the above answer, this is how I did it.
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" MaxHeight="{Binding Converter={StaticResource ListBoxHeightToItemsPanelHeightConverter}, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualHeight}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
In my converter I simply subtract 30 to account for the height of the header.
Here is the complete code:
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Margin="8" FontSize="18" TextAlignment="Center" FontWeight="Bold" Foreground="White" >
<TextBlock.Text>
<Binding Path="Name"/>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" MaxHeight="{Binding Converter={StaticResource ListBoxHeightToGroupStyleHeightConverter}, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualHeight}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
<!-- Your template here. -->
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate >
<!-- Your template here. -->
</DataTemplate>
</ListBox.ItemTemplate>
Hope this helps save someone some time!

Resources