WPF: How to access Element in ListView.ItemTemplate? - wpf

I need to access element named "PageHost" for the selected list item in the following XAML code from C# codebehind, how to do so please ?
<ListView.Resources>
<p:PageWidthConverter x:Key="PageWidthConverter" />
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate x:Name="PagesViewDataTemplate">
<DataTemplate.Resources>
<Style x:Key="PageHostStyle" TargetType="{x:Type p:PageHost}">
<Setter Property="Width" Value="{Binding Path=ActualWidth,
Converter={StaticResource PageWidthConverter},
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Grid}}}"
/>
</Style>
</DataTemplate.Resources>
<p:PageHost x:Name="PageHost">
</p:PageHost>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" VerticalAlignment="Top">
<WrapPanel.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="1"></ScaleTransform>
</WrapPanel.LayoutTransform>
</WrapPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListItem>
</ListItem>
</ListView>

I guess the below idea will work, though I am not verified the code. You need to find out the ContentPresenter Associated with the SelectedItem first, then using the DataTemplate we can find out the pageHost
ContentPresenter lstContent = lstViewInstance.ItemContainerGenerator.ContainerFromIndex(lstViewInstance.SelectedIndex) as ContentPresenter;
DataTemplate pageViewDataTemplate= this.FindResource("PagesViewDataTemplate") as DataTemplate;
PageHost pageHost = pageViewDataTemplate.FindName("PageHost", lstContent) as PageHost;

Related

Is there a way to set the ZIndex of different ItemsControl within the same canvas

I'm trying to set the ZIndex of different ItemsControls within a canvas and initially I did this which worked fine. Each of the following Collections was organised as expected.
<ItemsControl ItemsSource="{Binding AllPoints.PointsObjects}" Panel.ZIndex={Binding ZIndex}>
<ItemsControl ItemsSource="{Binding AllTracks.TrackObjects}" Panel.ZIndex={Binding ZIndex}>
However I need to be able to change the ZIndexes of each item within each ItemsControl individually. So I moved the ZIndex Binding to each individual object and tried to set the ZIndex using ItemsControl.ItemContainerStyle. But the collections did not appear in the order as expected.
<ItemsControl ItemsSource="{Binding AllPoints.PointsObjects}">
<ItemsControl.Resources>
<!--Resource dictionary template-->
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.ZIndex" Value="{Binding ZIndex}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
<ItemsControl ItemsSource="{Binding AllTracks.TrackObjects}">
<ItemsControl.Resources>
<!--Resource dictionary template-->
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.ZIndex" Value="{Binding ZIndex}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
Would I need to create just one ItemsControl or is it possible to link different ItemsControl's ZIndexes by use ItemsControl.ItemContainerStyle?
Following Clemens answer to my post this is the solution to my question. Within the Windows.Resources.
<Window.Resources>
<CollectionViewSource x:Key="Points" Source="{Binding AllPoints.PointsObjects}"/>
<CollectionViewSource x:Key="Tracks" Source="{Binding AllTracks.TrackObjects}"/>
<CompositeCollection x:Key="CombinedCollection">
<CollectionContainer Collection="{Binding Source={StaticResource Points}}" />
<CollectionContainer Collection="{Binding Source={StaticResource Tracks}}" />
</CompositeCollection>
</Window.Resources>
And within the Canvas.
<Canvas>
<ItemsControl ItemsSource="{StaticResource CombinedCollection}">
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Panel.ZIndex" Value="{Binding ZIndex}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Canvas>

How to resize ListBoxItems in a horizontal ListBox as the number of items grows [duplicate]

I have a problem with my ListBox in WPF. First of all, I have a horizontal ListBox with custom ItemTemplate. Now, I want to stretch the items, so that the items fits over the complete width of the ListBox. I tried things like setting the HorizontalContentAlignment to Stretch, but this still not working.
Here is my ItemTemplate:
<DataTemplate x:Key="ListViewStepTemplate">
<Grid VerticalAlignment="Stretch">
<TextBlock Text="{Binding Path=Title}"
FontSize="15"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
<Image Height="16"
Width="16"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Source="/images/Content/check_16x16.png"
Visibility="{Binding Path=IsDone, Converter={StaticResource BooleantoVisibilityConverter}, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</DataTemplate>
And this is my ListBox:
<ListBox DockPanel.Dock="Top"
ItemsSource="{Binding AllItemsList}"
SelectedItem="{Binding CurrentItem}"
ItemTemplate="{StaticResource ListViewStepTemplate}"
Height="60"
HorizontalContentAlignment="Stretch">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsEnabled" Value="{Binding IsEnabled, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="30 0" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
If there are 4 items, each item should have a width of 25%. If there are 5 items, each item should have a width of 20% and so on.
Is it possible to do what I want to do? I tried a lot of things now, but it does never work.
Instead of using StackPanel use UniformGrid
Provides a way to arrange content in a grid where all the cells in the grid have the same size.
and bind number of columns to number of items in the list and disable horizontal scrolling functionality.
<ListBox
...
ItemsSource="{Binding AllItemsList}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1" Columns="{Binding AllItemsList.Count}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<!-- style -->
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Don't use a StackPanel, use an UniformGrid instead.
<ItemsPanelTemplate>
<UniformGrid Rows="1" Columns="{Binding DataContext.Count, RelativeSource={RelativeSource Self}}"/>
</ItemsPanelTemplate>

Changing mouseover effect on Mahapps Tile

So recently I've started using MahApps.Metro for an application.
It's been going great, but one problem I cannot solve is MouseOver effect on a Tile.
I have a Grid, in which there's an Expander that hosts all the Tiles each of which represent a connection to the specific database. They are bound to an ObservableCollection which I populate from another database.
<Grid>
<Expander Margin="5" Header="Server Connections">
<ListBox ItemsSource="{Binding OmsConnections}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<controls:Tile
Title="{Binding Name}"
controls:ControlsHelper.MouseOverBorderBrush="{DynamicResource BlackBrush}"
Background="{DynamicResource GrayBrush2}"
Command="{Binding DataContext.TileClickCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}"
HorizontalTitleAlignment="Left"
Style="{StaticResource LargeTileStyle}"
TiltFactor="2">
<Image
Width="60"
Height="60"
Source="{Binding OmsConnectionTypeId, Converter={StaticResource ConnectionTypeToIconConverter}}" />
</controls:Tile>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Expander>
</Grid>
This is the style applied via Style
<Style x:Key="LargeTileStyle" TargetType="controls:Tile">
<Setter Property="Height" Value="125" />
<Setter Property="TitleFontSize" Value="14" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
<Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
<Setter Property="Width" Value="210" />
</Style>
So Whenever I mouseover an item I get the black border as specified, and this Orange Background Color (Which, if I'm not mistaken, is AccentColorBrush3) and I have no idea how to change it.
Here's the Image, since my rep is low and i cannot embed it.
Also, I'm really, really bad with Templates and Styles, so this is pretty much what i scrapped from the internet. ANY Feedback would be much appreciated for both the way I Bound to a collection and how to change the MouseOver color.
You could "override" the AccentColorBrush3 resource by adding a SolidColorBrush resource to the ListBox:
<ListBox ItemsSource="{Binding OmsConnections}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<!-- Specify the highlight brush here: -->
<ListBox.Resources>
<SolidColorBrush x:Key="AccentColorBrush3" Color="Yellow" />
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<controls:Tile
Title="{Binding Name}"
controls:ControlsHelper.MouseOverBorderBrush="{DynamicResource BlackBrush}"
Background="{DynamicResource GrayBrush2}"
Command="{Binding DataContext.TileClickCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}"
HorizontalTitleAlignment="Left"
Style="{StaticResource LargeTileStyle}"
TiltFactor="2">
<Image Width="60"
Height="60"
Source="{Binding OmsConnectionTypeId, Converter={StaticResource ConnectionTypeToIconConverter}}" />
</controls:Tile>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Bind adorner property to viewmodel property

I need to display (or not) an adorner depending on a viewmodel's property.
My view is like this :
<ItemsControl x:Name="Items">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=X}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
<Setter Property="Width" Value="{Binding Path=Width}" />
<Setter Property="Height" Value="{Binding Path=Height}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<AdornerDecorator>
<Border x:Name="DraggableBorder" Background="{Binding Path=BackgroundColor}">
<!-- contents -->
<i:Interaction.Behaviors>
<behaviors:DragOnCanvasBehavior DraggableItem="{Binding}">
<behaviors:DragOnCanvasBehavior.MouseOverAdornerTemplate>
<DataTemplate>
<Border DataContext="DraggableBorder"
BorderBrush="#B0000000"
Width="{Binding Path=Width}"
Height="{Binding Path=Height}" />
</DataTemplate>
</behaviors:DragOnCanvasBehavior.MouseOverAdornerTemplate>
<behaviors:DragOnCanvasBehavior.SelectedAdornerTemplate>
<DataTemplate>
<Border DataContext="DraggableBorder"
BorderBrush="#FF34619E"
Width="{Binding Path=Width}"
Height="{Binding Path=Height}"
Visibility="{Binding Path=Selected,
ElementName=DraggableBorder,
Converter={StaticResource BooleanToVisibilityConverter}}" />
</DataTemplate>
</behaviors:DragOnCanvasBehavior.SelectedAdornerTemplate>
</behaviors:DragOnCanvasBehavior>
</i:Interaction.Behaviors>
</Border>
</AdornerDecorator>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And the behavior attaches the mouse events to the proper methods, and displays/hides the mouse over adorner.
The mouse over/out events and adorners are working fine, but the selection adorners cause me a bit of trouble. Because only one item should be selected, I want to rely on the Selected property of the viewmodel. I assumed what is in the sample above would work (I tried a few versions), but alas, it is not to be.
How should I write my Visibility property ?
Full code available here : https://github.com/cosmo0/DragSnap/tree/adorners
The Visibility binding binds with a property 'Selected' of DraggableBorder, which does not exist.
Furthermore, the border has a DataContext="DraggableBorder" which in this case, is a simple string.
So, use the following properties on your border:
<Border DataContext="{Binding DataContext, ElementName=DraggableBorder}" Visibility="{Binding Selected, Converter=...}"/>

Tabbing User Control In Listbox DataTemplate

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

Resources