Stretch line to width of Itemstemplate canvas in itemscontrol - wpf

I have this code. For some reason I can't get the contentpresenter to stretch to fill the width of the canvas. Several of my attempts are commented out in the xaml.
<ItemsControl ItemsSource="{Binding MarkerLocations, Mode=OneTime}" HorizontalContentAlignment="Stretch">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Top" Value="{Binding}" />
<Setter Property="Canvas.Left" Value="0" />
<!--Setter Property="Width" Value="{Binding Path=Width, RelativeSource={RelativeSource FindAncestor, AncestorType=Canvas, AncestorLevel=1}}"/-->
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--Rectangle Stroke="Black" Height="2" Stretch="Fill"/-->
<Line Stretch="Fill" X2="2" Y1="{Binding Mode=OneTime}" Y2="{Binding Mode=OneTime}" Stroke="Black" StrokeThickness="1"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have a feeling I'm not understanding the context of the ItemContainters.

If you want to bind to the width of stretching objects you should bind to the ActualWidth:
{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Canvas}}
Edit: This may not be necessary
Canvases have the habit of not occupying any space at all unless you tell them:
<ItemsControl ItemsSource="{Binding MarkerLocations, Mode=OneTime}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Red"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Setting its Background is a useful "layout-debugging" trick to see if its actually there. From there one of your approaches should work.

Related

How can I transform a border but not the content inside?

Here is an image of my problem and my code below. I'd like to know how I can get the text to be flipped right side up. Below is also a link where I got the suggestions for setting scale transform Y to 1.
https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-flip-a-uielement-horizontally-or-vertically
<Viewbox>
<Grid>
<ItemsControl ItemsSource="{Binding FaceParts}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="SlateBlue" Height="140" Width="80" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="RenderTransform" Value="1 0 0 -1 0 0"/>
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Border Width="{Binding Width}" Height="{Binding Height}" Background="{Binding Fill}" BorderBrush="Black" BorderThickness=".20">
<Viewbox>
<TextBlock Text="{Binding TextOverlay}" RenderTransformOrigin=".5,.5">
<TextBlock.RenderTransform>
<ScaleTransform ScaleY="1"/>
</TextBlock.RenderTransform>
</TextBlock>
</Viewbox>
</Border>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Viewbox VerticalAlignment="Bottom" Height="5" Margin="0,0,0,5">
<TextBlock Background="SlateBlue" TextAlignment="Center" Text="{Binding SelectedViewerProduct.Width, Converter={StaticResource FractionConverter}}"/>
</Viewbox>
</Grid>
</Viewbox>
As it turns out, setting ScaleY to a positive has no effect on flipping it right side up, in order to flip it right side up, I had to set the ScaleY to a -1. Essentially flipping it over again the opposite direction to make it right side up.

WidthConverter is not trigger when GroupBox has been resize

GroupBox has an auto column width. I can't think anymore why WidthConverter is not triggered when GroupBox has been resized. Any alternatives?
The goal is to display 5 rows and 5 columns always. When user resized the window, the column width must also resized. TIA!
<GroupBox Grid.Column="0" Grid.ColumnSpan="7" Grid.Row="10" x:Name="GbSerial"
Template="{StaticResource GbSerialProgrammed}">
<GroupBox.Header>
<TextBlock TextDecorations="Underline" FontWeight="Bold" FontSize="24" HorizontalAlignment="Center" TextAlignment="Center"
Text="{lgg:Lgg Path=AllSerialNumberProgrammed}"/>
</GroupBox.Header>
<ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
<ItemsControl x:Name="IcSerialNumbers" Background="White" Tag="{Binding ElementName=GbSerial, Path=ActualWidth}"
ItemsSource="{Binding AllSerialNumberProgrammed, UpdateSourceTrigger=PropertyChanged}"
helper:ItemsControlHelper.ScrollToLastItem="True"
FontSize="24" Height="250" >
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Height" Value="50"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Width" Value="{Binding ElementName=GbSerial,
Path=ActualWidth, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True,
Mode=OneTime, Converter={StaticResource WidthConverter},
ConverterParameter=5}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" FlowDirection="LeftToRight" Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl >
</ScrollViewer>
</GroupBox>
Mode OneTime, as name implies, means it is invoked only once when it starts off.

How to force element list to fill the windows on a wrappanel?

I try to do a list of columns on a window and I want to have the same result than in a Grid when I use the *.
<ListView ItemsSource="{Binding UcColumns}"
HorizontalContentAlignment="Stretch"
VerticalAlignment="Stretch"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Margin="0"
Orientation="Horizontal" Background="WhiteSmoke"
>
</WrapPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
The problem is that the Wrappanel content width and height is depending of it proper content but not of the window size.
I hope you can help me.
Thx.
Try this:
<WrapPanel IsItemsHost="True" Margin="0" Orientation="Horizontal" Background="WhiteSmoke"
Width="{Binding ActualWidth,
RelativeSource={RelativeSource AncestorType={x:Type ScrollContentPresenter}, Mode=FindAncestor}}"
Height="{Binding ActualHeight,
RelativeSource={RelativeSource AncestorType={x:Type ScrollContentPresenter}, Mode=FindAncestor}}">
I don't know why you want wrappanel here, but if you want your listviewitem content to stretch to the listview width then you can put the ListView.ItemContainerStyle like below:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
And set the itemtemplate like:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<local:MyuserControl HorizontalAlignment="Stretch"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
This will stretch your items
Thanks a lot for helping me.
I combinate your answer and with some other search I solve this problem as write under.
<ListView ItemsSource="{Binding UcColumns}"
HorizontalContentAlignment="Stretch"
VerticalAlignment="Stretch"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate >
<uc:UC_Column HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="{Binding ActualWidth,
Converter={cv:DivideConverter},
ConverterParameter=3,
RelativeSource={RelativeSource AncestorType={x:Type ScrollContentPresenter}, Mode=FindAncestor}}"
Height="{Binding ActualHeight,
RelativeSource={RelativeSource AncestorType={x:Type ScrollContentPresenter}, Mode=FindAncestor}}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
One time again : thank you !

Canvas binding in silverlight

I'm trying to create a canvas, with items located at specefied locations on the canvast, as i can not bind an source and a template directly to a Canvas, have i used a ItemsControl.
But there are a problem all the items are located at 0,0. And i have tested the Bindings they do not return 0,0.
How can i make this work so the items are located at the right place?
Also is it poissible to create 2 layers on the canvas, where each layer is binded to a diffrent source, and uses a diffrent template?
This is in Silverlight
<ItemsControl Grid.Row="1" Grid.Column="1"
Width="650" Height="650"
ItemsSource="{Binding Skills}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Margin="0"
Width="650" Height="650" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Canvas.Top="{Binding Top}" Canvas.Left="{Binding Left}">
<TextBlock Text="{Binding Name}" />
<Image Source="{Binding Icon}" />
<StackPanel Orientation="Horizontal" >
<TextBlock FontWeight="Bold" TextAlignment="Center" Text="{Binding SkillPointsStatusText}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Test with ItemContainerStyle
<ItemsControl Grid.Row="1" Grid.Column="1"
Width="650" Height="650"
ItemsSource="{Binding Skills}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Margin="0"
Width="650" Height="650" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" />
<Image Source="{Binding Icon}" />
<TextBlock FontWeight="Bold" TextAlignment="Center" Text="{Binding SkillPointsStatusText}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Top" Value="{Binding Top}" />
<Setter Property="Canvas.Left" Value="{Binding Left}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
Well i have droped the project, but i will leave the question open should one have an anwser
All of the following does not work in SL4 since it depends on bindings in a Setter.Value.
Try setting the binding in the ItemContainerStyle since your StackPanel is not the root element; your template will be placed in a ContentPresenter, so your attached properties for canvas positioning in the StackPanel will be ignored.
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Top" Value="{Binding Top}" />
<Setter Property="Canvas.Left" Value="{Binding Left}" />
</Style>
</ItemsControl.ItemContainerStyle>
Edit: If Silverlight does not support ItemContainerStyle you can set the universal style for ContentPresenters which should work just as well:
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.Resources>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Left}"/>
<Setter Property="Canvas.Top" Value="{Binding Top}"/>
</Style>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

How do I use a Silverlight2 ItemsControl to position a collection of items on a canvas?

In WPF, you can create a ListBox with a Canvas as an ItemsPanel and position items on that canvas. The code to do that looks something like this:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="200" Height="200"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Canvas.Left" Value="{Binding Path=XPos}"/>
<Setter Property="Canvas.Top" Value="{Binding Path=YPos}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Can you do the same thing in a Silverlight2 ListBox, or preferably an ItemsControl?
I've found a solution, but (to me) it smells.
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Canvas Width="200" Height="200">
<TextBlock
Text="{Binding Path=Name}"
Canvas.Left="{Binding Path=XPos}"
Canvas.Top="{Binding Path=YPos}" />
</Canvas>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="200" Height="200"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Each item has its own canvas, so they end up stacked on top of eachother.

Resources