I have a small problem how to set the ItemsControl Property Width. I use Datatemplates to fill my ItemControl. Every Item is a small Grid (Text and Rectangle) in a Canvas.
When I use the ItemsControl in a Window the ActualWidth (and DesiredWidth) is always 0.0.
Only when i hardcode the Width Property of the Canvas the ItemsControl has a size. But that is far from perfect. I would rather like when the Control gets the width (or DesiredWidth) from the biggest Item.
Here is a short code sample:
<ItemsControl ItemsSource="{Binding mySource}"
ItemTemplate="{DynamicResource myTemplate}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type type:myType}" x:Key="myTemplate">
<Grid Width="Auto" Height="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="1"
Height="1"
HorizontalAlignment="Stretch"
Fill="Blue"/>
<TextBlock Grid.Row="0"
Grid.Column="1"
Margin="3"
Text="{Binding Text}"
FontWeight="Bold"
TextWrapping="Wrap"
TextAlignment="Left"/>
</Grid>
</DataTemplate>
<v:PositionMultiConverter x:Key="PositionMultiConverter"/>
</ItemsControl.Resources>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Bottom">
<Setter.Value>
<MultiBinding Converter="{StaticResource ResourceKey=PositionMultiConverter}">
<Binding Path="Position"/>
<Binding Path="ActualHeight" ElementName="canvas"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="canvas" IsItemsHost="True" Width="20"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
Related
I have a grid that contains 2 controls, a dynamic grid and an expander. For some reason, with these column definitions, the expander expands but the second inner/dynamic grid doesn't not resize/shrink - i know it's something with the grid but i don't know what.
This is a snippet of the xaml:
<Grid Grid.Column="0" Grid.Row="1"
IsHitTestVisible="{Binding Path=(run),
Converter={StaticResource InverseBooleanConverter}}"
Name="mainGrid"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
MinWidth="{Binding GridWidth}" MinHeight="{Binding GridHeight}"
utils:SizeObserver.Observe="True"
utils:SizeObserver.ObservedHeight="{Binding GridHeight,
Mode=OneWayToSource}"
utils:SizeObserver.ObservedWidth="{Binding GridWidth,
Mode=OneWayToSource}">
<ItemsControl x:Name="eItemControl" ItemsSource="{Binding eCompositeCollection}">
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Row}"/>
<Setter Property="Grid.Column" Value="{Binding Column}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Name="wGrid" Grid.Row="1"
MinWidth="{Binding MinWidth, ElementName=mainGrid}"
MinHeight="{Binding MinHeight, ElementName=mainGrid}"
utils:GridHelper.RowCount="{Binding RowCount}"
utils:GridHelper.StarRows="{Binding StarRows}"
utils:GridHelper.ColumnCount="{Binding ColumnCount}"
utils:GridHelper.StarColumns="{Binding StarColumns}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type engine:Wodel}">
<ToggleButton
Tag="{Binding}"
Height="{Binding ElementName=eItemControl,
Path=DataContext.nHWidth}"
Width="{Binding ElementName=eItemControl,
Path=DataContext.nHWidth}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="{Binding ElementName=eItemControl,
Path=DataContext.BMargin}"
Padding="2"
Style="{StaticResource Wbutton}">
</ToggleButton>
</DataTemplate>
<DataTemplate DataType="{x:Type erModel}">
<TextBlock Text="{Binding jName}" Style="{StaticResource GridHeaders}"/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
<ItemsControl ItemsSource="{Binding huil}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Width="{Binding Width}" Height="{Binding Height}"
Visibility="{Binding Visibility}">
<Rectangle.RenderTransform>
<TranslateTransform X="{Binding X}" Y="{Binding Y}"/>
</Rectangle.RenderTransform>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
<Expander Grid.Column="1" Grid.Row="1" IsExpanded="False" ExpandDirection="Right">
// SOME EXPANDER CODE
</Expander>
And the original Grid definitions in the parent grid that these are both in:
<Grid.RowDefinitions>
<RowDefinition Height="0.1*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="0.1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
If anyone can please help as I really don't know where to go from here and what the problem may be...
Removing this from the parent grid fixed it.... trying to figure out why... ?
MinWidth="{Binding GridWidth}" MinHeight="{Binding GridHeight}"
I am creating UWP application. There is a listview, with groups.
XAML code goes like this:
<Page.Resources>
<CollectionViewSource x:Name="ContactsCVS" IsSourceGrouped="True" />
<!-- When using x:Bind, you need to set x:DataType -->
<DataTemplate x:Name="ContactListViewTemplate" x:DataType="data:Contact">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse x:Name="Ellipse"
Grid.RowSpan="2"
Width ="32"
Height="32"
Margin="6"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Fill="LightGray"/>
<TextBlock Grid.Column="1"
Text="{x:Bind Name}"
x:Phase="1"
Style="{ThemeResource BaseTextBlockStyle}"
Margin="12,6,0,0"/>
<TextBlock Grid.Column="1"
Grid.Row="1"
Text="{x:Bind Position}"
x:Phase="2"
Style="{ThemeResource BodyTextBlockStyle}"
Margin="12,0,0,6"/>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListView ItemsSource="{x:Bind ContactsCVS.View}"
ItemTemplate="{StaticResource ContactListViewTemplate}"
SelectionMode="Single"
ShowsScrollingPlaceholders="True"
Grid.Row="1"
Grid.ColumnSpan="2" x:Name="listViewMain">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate x:DataType="data:GroupInfoList">
<TextBlock Text="{x:Bind Key}"
/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
And everything is ok, except that I want to make each group to have some kind of border. Like this:
How to achieve this?
As #Ken Tucker said, you can edit the GroupStyle and use GroupStyle.Panel property to add a border for each group. For example, using a GroupStyle like the following:
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate x:DataType="data:GroupInfoList">
<TextBlock Text="{x:Bind Key}"
Style="{ThemeResource TitleTextBlockStyle}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<StackPanel BorderBrush="Red" BorderThickness="1" Margin="8,0,18,0" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
However, you may find there is no effect with using this GroupStyle in your code. This is because GroupStyle.Panel can't work with UI virtualization. If the ListView uses a virtualizing panel such as ItemsWrapGrid or ItemsStackPanel, then GroupStyle.Panel won't have effect. And for ListView its default ItemsPanel is a ItemsStackPanel. So you will also need to change ListView's ItemsPanel like:
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
Then you should be able to see the border for each group. For more info, please refer to this case. And also please note that using GroupStyle.Panel might influence the performance as the lack of UI virtualization. You may consider whether to use this according to your real scenario.
How to stretch GridViewItem horizontaly? Trying to set property HorizontalContentAlignment or style property in ItemContainerStyle. This does not help.
Here is a code:
<GridView ItemsSource="{x:Bind Banks}" SelectionMode="None" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</GridView.ItemContainerStyle>
<GridView.ItemTemplate>
<DataTemplate x:DataType="model:Bank">
<Grid HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" Grid.Column="0" />
<GridView ItemsSource="{x:Bind Departments}" Grid.Row="1" HorizontalContentAlignment="Stretch" IsItemClickEnabled="True" VerticalContentAlignment="Stretch">
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</GridView.ItemContainerStyle>
<GridView.ItemTemplate>
<DataTemplate x:DataType="model:Department">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" Grid.Column="0" />
<TextBlock Text="{Binding Address}" Grid.Column="0" Grid.Row="1" />
<TextBlock Text="{Binding USD.Date}" Grid.Column="1" Grid.RowSpan="2"/>
<TextBlock Text="{Binding USD.Sell}" Grid.Column="2" />
<TextBlock Text="{Binding USD.Buy}" Grid.Column="2" Grid.Row="1"/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
By default,GridView uses ItemsWrapGrid as the panel to position and arrange GridViewItem, you can find this from Live Visual Tree:
Although you've set HorizontalContentAlignment or HorizontalAlignment to Stretch for GridViewItem, but the size of GridViewItem is limited by ItemsWrapGrid.
ItemsWrapGrid positions child elements sequentially from left to right or top to bottom in an ItemsControl that shows multiple items. When elements extend beyond the container edge, elements are positioned in the next row or column.
So in ItemsWrapGrid, items won't be stretched.
If you want to stretch GridViewItem horizontaly, we can use ItemsStackPanel instead of ItemsWrapGrid like following:
In Resources, add a ItemsPanelTemplate with ItemsStackPanel:
<Page.Resources>
<ItemsPanelTemplate x:Key="MyItemsPanelTemplate">
<ItemsStackPanel />
</ItemsPanelTemplate>
</Page.Resources>
Then use this template in GridView:
<GridView HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
ItemsPanel="{StaticResource MyItemsPanelTemplate}"
ItemsSource="{x:Bind Banks}"
SelectionMode="None">
...
<GridView Grid.Row="1"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
IsItemClickEnabled="True"
ItemsPanel="{StaticResource MyItemsPanelTemplate}"
ItemsSource="{x:Bind Departments}">
...
</GridView>
...
</GridView>
Or we can use ListView instead of GridView as ListView's default ItemsPanel is ItemsStackPanel.
<Grid Name="WeightGrid" Grid.RowSpan="2" SnapsToDevicePixels="True" Grid.ColumnSpan="2" Margin="{Binding WeigntGridMargin}" MouseDown="WeigntGridWrap_OnMouseDown" MouseMove="WeigntGridWrap_OnMouseMove" MouseUp="WeigntGridWrap_OnMouseUp">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
...
</Grid.ColumnDefinitions>
<Grid.RenderTransform>
<TranslateTransform x:Name="weightTT"/>
</Grid.RenderTransform>
<StackPanel Grid.Column="0" Width="100" Height="75">
<StackPanel.Background>
<ImageBrush ImageSource="/Size.WPF;component/Assets/ruller-bg.png" />
</StackPanel.Background>
<TextBlock Margin="0, 42, 0, 0" Foreground="#c0b6d1" HorizontalAlignment="Center" FontSize="18">0</TextBlock>
</StackPanel>
<StackPanel Grid.Column="1" Width="100" Height="75">
<StackPanel.Background>
<ImageBrush ImageSource="/Size.WPF;component/Assets/ruller-bg.png" />
</StackPanel.Background>
<TextBlock Margin="0, 42, 0, 0" Foreground="#c0b6d1" HorizontalAlignment="Center" FontSize="18">1</TextBlock>
</StackPanel>
<StackPanel Grid.Column="2" Width="100" Height="75">
<StackPanel.Background>
<ImageBrush ImageSource="/Size.WPF;component/Assets/ruller-bg.png" />
</StackPanel.Background>
<TextBlock Margin="0, 42, 0, 0" Foreground="#c0b6d1" HorizontalAlignment="Center" FontSize="18">2</TextBlock>
</StackPanel>
...
</Grid>
I have Grid with many columns. Every column is StackPanel with different column number and with different number in TextBlock. To decrease amount of code I want to use ItemsContol or something like this to build grid columns. But one problem - How can I bind ColumnNumber to ItemsControl Item? Possibly there is solution Bind Grid.Row / Grid.Column inside a DataTemplate But another problem - How can set amount of Columns?
UPD :
<ItemsControl Name="WeightItemsControl" ItemsSource="{Binding Cells}" Grid.RowSpan="2" Grid.ColumnSpan="2">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid Name="WeightGrid" SnapsToDevicePixels="True" Margin="{Binding WeigntGridMargin}" MouseDown="WeigntGridWrap_OnMouseDown" MouseMove="WeigntGridWrap_OnMouseMove" MouseUp="WeigntGridWrap_OnMouseUp">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding GridRow}" />
<Setter Property="Grid.Column" Value="{Binding GridColumn}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
This is what I have now. But I still don't know how to set Amount of columns that should be created to it ItemsControl (Currently it's just binded to some collection Cells but it should be just number as amount of columns).
<ItemsControl Name="icTodoList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Title}" />
<ProgressBar Grid.Column="1" Minimum="0" Maximum="100" Value="{Binding Completion}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
you can modify the code as you want..or if you don't use the binding you can simply do like this
<ItemsControl>
<system:String>ItemsControl Item #1</system:String>
<system:String>ItemsControl Item #2</system:String>
<system:String>ItemsControl Item #3</system:String>
<system:String>ItemsControl Item #4</system:String>
<system:String>ItemsControl Item #5</system:String>
</ItemsControl>
I am defining a ListView like this:
<DataTemplate x:Key="LibraryItemTemplate">
<Grid Height="191"
UseLayoutRounding="True">
<Grid.Background>
<ImageBrush Stretch="Fill"
ImageSource="Assets/BookShelf.jpg" />
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid x:Name="gridTitle"
Background="{Binding Text, Converter={StaticResource LibraryItemBackgroundConverter}, ElementName=tbTitle}"
Margin="6,4,6,13">
<TextBlock x:Name="tbTitle"
TextWrapping="Wrap"
VerticalAlignment="Center"
RenderTransformOrigin="0.5,0.5"
Width="100"
Margin="0,0,0,0.2"
TextAlignment="Center"
FontSize="24"
FontWeight="Bold"
UseLayoutRounding="False"
d:LayoutRounding="Auto">
<TextBlock.RenderTransform>
<CompositeTransform Rotation="-90" />
</TextBlock.RenderTransform>
<Run Text="{Binding Title}" />
</TextBlock>
</Grid>
<Grid x:Name="gridBooks"
Grid.Column="1"
Margin="0">
<GridView x:Name="booksGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
ItemsSource="{Binding Items}"
ItemTemplateSelector="{StaticResource textbookTemplateSelector}"
SelectionMode="Multiple"
IsItemClickEnabled="True"
ItemClick="booksGridView_ItemClick"
SelectionChanged="booksGridView_SelectionChanged"
IsSwipeEnabled="false"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</Grid>
</Grid>
</DataTemplate>
<Grid Grid.Row="1"
Margin="80,0,12,0">
<ListView x:Name="libraryListView"
AutomationProperties.AutomationId="VideoListView"
AutomationProperties.Name="Videos"
TabIndex="1"
Padding="0,0,4,0"
ItemsSource="{Binding}"
IsSwipeEnabled="False"
SelectionChanged="LibraryListView_SelectionChanged"
ItemTemplate="{StaticResource LibraryItemTemplate}"
ItemContainerStyle="{StaticResource LibraryListViewItemStyle}">
</ListView>
</Grid>
The problem I am having is that each ListViewItem has different width, based on the number of elements in the GridView.
How can I force each ListViewItem to use the maximum width of the screen (so that the "Assets/BookShelf.jpg" will be the same for each of the ListViewItems).
Please see the attached image to better demonstrate my problem.
Thanks
To give you the best answer I would need a dummy screenshot of the expected layout, but it sound like you want the right column to stretch, which would be accomplished by setting its width to star (*) instead of Auto (which takes up only the space needed).
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <!-- ONLY TAKE UP SPACE NEEDED -->
<ColumnDefinition Width="*" /> <!-- TAKE UP ALL AVAILABLE SPACE -->
</Grid.ColumnDefinitions>
The answer is with this code:
<ListView ..>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalAlignment" Value="Strech" />
.
.
.
.
<Setter Property="HorizontalContentAlignment" Value="Strech" />
</Style>
</ListView.ItemContainerStyle>
...
</ListView>
In this code we set the ItemContainerStyle: HorizontalAlignment = "Strech" and HorizontalContentAlignment = "Strech" and it made the trick.