Make a UIElement's width auto but not autofit to its parent? - c#

Does anyone know how to make a UIElement's width auto but not autofit to its parent? I want it to expand past the container (even if it's cut off.)
Right now it does this:
I want it to do this:
I am able to achieve this if I define the width in xaml but I'd like to do it with auto.
Xaml:
<UserControl.Resources>
<DataTemplate x:Key="ItemTemplate">
<StackPanel>
<TextBlock Text="{Binding RandomValues}"/>
</StackPanel>
</DataTemplate>
<ItemsPanelTemplate x:Key="UniformGridPanel">
<UniformGrid Rows="1" HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</UserControl.Resources>
<ListBox HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="Auto" DataContext="{Binding}" ItemTemplate="{DynamicResource ItemTemplate}" ItemsSource="{Binding Collection}" ItemsPanel="{DynamicResource UniformGridPanel}" Style="{DynamicResource ListBoxStyle}"/>

Related

Grouping issue in Virtualizing Wrap Panel

I am displaying around 1000+ images in my WPF application. All these images are grouped using "GroupID" property. Since I have to take care of memory ,I have used VirtualizingStackPanel and secondly I am using WrapPanel to display all these images as per space accumulated by my ListView.
My solution works fine for small set of images and WPF wrap panel removes the Virtualization effect when items are grouped. Thus i googled this problem and found out we can use VirtualWrapPanel.
I tried it but i started to get Exception
"_owner was null." at VirtualWrapPanel
"_owner.InvalidateScrollInfo();"
MainWindow.cs
List<SearchData> myData = new List<SearchData>();
GetData(ref myData);
listView.ItemsSource = myData;
//Grouping code
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(myData);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("GroupId");
view.GroupDescriptions.Add(groupDescription);
MainWindow.cs
<Window x:Class="WpfItemVirtualization.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfItemVirtualization"
xmlns:dz="clr-namespace:DevZest.Windows.DataVirtualization;assembly=DevZest.DataVirtualization"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="ListViewItem">
<Setter Property="dz:VirtualListItemBase.AutoLoad" Value="true" />
</Style>
<DataTemplate x:Key="ThumbGridTemplate" >
<VirtualizingStackPanel x:Name="OuterStackPanel" Height="253" Width="230" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Background="White">
<VirtualizingStackPanel x:Name="InnerStackPanel" Height="{Binding Height, ElementName=OuterStackPanel}" Width="{Binding Width, ElementName=OuterStackPanel}" >
<Grid Margin="0,0,0,0" Height="253" Background="#FFCDCDCD">
<TextBlock TextTrimming="CharacterEllipsis" Text="{Binding FilePath}" FontFamily="Segoe UI" Foreground="Black" HorizontalAlignment="Left" TextAlignment="Left" Margin="0" FontSize="12" Height="20" Background="{x:Null}" Width="Auto" VerticalAlignment="Top"/>
</Grid>
</VirtualizingStackPanel>
</VirtualizingStackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListView x:Name="listView"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
ScrollViewer.IsDeferredScrollingEnabled="True"
dz:GridViewSort.AutoSort="True"
dz:VirtualListLoadingIndicator.IsAttached="False" ItemTemplate="{StaticResource ThumbGridTemplate}"
Margin="0,35,0,0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<local:VirtualizingWrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Background="#FF3E3E3E" Height="30" Margin="0,1,0,1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding GroupId, StringFormat={}Duplicate \Group {0}}" Foreground="Black" FontSize="14" FontFamily="Segoe UI Semibold" VerticalAlignment="Center" Margin="20,0,0,0"/>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
Any suggestion will be helpful. Thank you.

Adding button outside the binded Listbox in xaml

I have encountered a problem - i have created a project where i bind my code to xaml by using a bind to the listbox. However, it has created some problems in my future code - i want to add button to my form, but i encounter some errors.
'Items collection must be empty before using ItemsSource.'
This Error occurs when i try to bind something outside of my bindable Listbox.
The property "VisualTree" can only be set once.
This Error occurs when i try to add button underneath the Listbox.
Can someone guide me on how can i fix this?
My code:
<ListBox x:Name="ItemsControl1">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5">
</UniformGrid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="2" Width="Auto" Height="Auto">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number}"/>
<Image Source="{Binding Source}" Margin="0,0,5,0"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The desirable result would be a button under the listbox.
You should add your button below ListBox declaration.
Exceptions you are facing are thrown because visual tree is populated via binding and you cannot alter it manually anymore.
You will need to put all this stuff inside of some layout container (Grid, StackPanel, etc.), since you cannot set Window's/UserControl's Content property twice:
<StackPanel>
<ListBox x:Name="ItemsControl1">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5">
</UniformGrid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="2" Width="Auto" Height="Auto">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number}"/>
<Image Source="{Binding Source}" Margin="0,0,5,0"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button/>
</StackPanel>

Horizontal Center Items inside VariableSizedWrapGrid

I have a VariableSizedWrapGrid, with buttons as items:
<Page.Resources>
<DataTemplate x:Key="LinkTemplate" x:DataType="local:LinkWeb">
<Button Width="100" Height="100" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="15,15,15,15" Click="Button_Click" >
<Button.Content>
<StackPanel>
<Image Source="{Binding ImageLink}" Margin="8,8,8,8" HorizontalAlignment="Center" Height="{Binding HeightImage}" Width="{Binding WidthImage}"/>
<TextBlock Text="{Binding Text}" TextWrapping="WrapWholeWords" />
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</Page.Resources>
...
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Grid.Row="1">
<ItemsControl x:Name="imageContent" ItemsSource="{Binding Enlaces}" ItemTemplate="{StaticResource LinkTemplate}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Horizontal" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalChildrenAlignment="Stretch" MaximumRowsOrColumns="2"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
The VariableSizedWrapGrid shows two items per row, but the items appears aligned to the left, as you can see:
I need the VariableSizedWrapGrid shows the items centered in his content, like this:
Any idea about how I can achieve this?
EDIT
I've tried center the ScrollViewer, and, yes, items are "a little more centered", because VariableSizedWrapGrid inside ScrollViewer is centered, but, inside VariableSizedWrapGrid items float to the left, so items are not centered as you can see in this picture:
You could set the HorizontalChildrenAlignment property value of VariableSizedWrapGrid as Center. It should work.
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Horizontal" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalChildrenAlignment="Center" MaximumRowsOrColumns="2" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

Overlapping Items in WPF ItemsControl

I am having a problem with DataTemplates used in a WPF ItemsControl. I want to be able to "bring forward" any of the items in the list so that they are on top of everything else in the list, but haven't had any luck.
Here's a simple example that illustrates the problem. What I want to see is achieved in the example using a WrapPanel and a bunch of colored blocks:
The first block overlaps the second. Good. When I try to do the same thing with the ItemsControl, the first block falls underneath the second, despite its ZIndex:
How can I make the first block overlap all the others in the ItemsControl?
From my understanding of the ZIndex property, I am assuming that I need to set the ZIndex higher up in the Visual Tree than the Border inside of the DataTemplate, but don't know how or where to do that.
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MainViewModel x:Key="mainViewModel" />
<DataTemplate DataType="{x:Type local:FireFighter}">
<Border Background="Pink" Padding="8" Panel.ZIndex="10" Margin="4">
<Border.RenderTransform>
<TranslateTransform X="18" Y="4"/>
</Border.RenderTransform>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type local:PoliceOfficer}">
<Border Background="Orange" Padding="8" Margin="4">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</Border>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ItemsControl DataContext="{StaticResource mainViewModel}"
ItemsSource="{Binding People}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<WrapPanel Margin="0,10,0,0">
<Border Background="Blue" Width="30" Height="30" Margin="4" Panel.ZIndex="10">
<Border.RenderTransform>
<TranslateTransform X="18" Y="4"/>
</Border.RenderTransform>
</Border>
<Border Background="Green" Width="30" Height="30" Margin="4"/>
<Border Background="Green" Width="30" Height="30" Margin="4"/>
</WrapPanel>
</StackPanel>
I found an answer that will work for my situation right here:
https://stackoverflow.com/a/9687758/4912801
It turns out that setting the Panel.ZIndex property wasn't working because WPF inserts a ContentPresenter element for each item in the ItemsControl. In my application, I was trying to get whatever element the mouse is hovering over to come to the front, so applying a style to all ContentPresenters in the ItemsControl allowed me to bring them to the front when the mouse was over them.
I was looking for something similar and this is what did it for me. Use a UniformGrid as your ItemsPanelTemplate, then change the margins on your DataTemplate to overlap as much as you want.
<Grid Grid.Row="1"
Grid.ColumnSpan="2">
<Grid.Resources>
<local:PointsToPathConverter x:Key="pointsToPathConverter"/>
</Grid.Resources>
<Image
Source="{Binding Bmp}"
Stretch="Fill"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" />
<ItemsControl ItemsSource="{Binding AllTraceLines}"
VerticalAlignment="Stretch"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Margin="0,-20,0,-20" Data="{Binding Converter={StaticResource pointsToPathConverter}}" Stroke="Red" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Stretch="Fill"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>

Trying To Make A Listbox Horizontal Inside a Grid [duplicate]

This question already has answers here:
I need Horizontal view of list boxes
(5 answers)
Closed 9 years ago.
I have a grid of size 400 x 150 in which I would like to add a Listbox.
The Listbox is composed of a grid that contains a TextBlock.
<Grid Width="400" Height="150">
<ListBox x:Name="list" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid Width = "80">
<Border BorderBrush="Black" HorizontalAlignment="Right" />
<TextBlock Foreground="Black" Text="{Binding name}" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
But the list is displayed vertically.
I tried to use a VirtualizingStackPanel but the problem is that the borders of the grids don't appear correctly.
How can I make this list look horizontal, with the borders of the grid that contains the textblock visible?
U can use like this to have horizontal scrollViewer of Listbox
<Grid Width="400" Height="150">
<ListBox x:Name="list" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Hidden" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate >
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal">
<Grid Width = "80">
<Border BorderBrush="Black" HorizontalAlignment="Right" />
<TextBlock Foreground="Black" Text="{Binding name}" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
In addition to this You have to adjust height and width of both listbox and grid according to your requirement.
If I am correct, you don't want a StackPanel inside the DataTemplate, you actually want a horizontally laid out items inside the ListBox. You need to change the ListBox.ItemsPanel and you need to disable vertical scroll and enable horizontal scroll in the ListBox. Here is the full XAML:
<ListBox ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Auto">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"
CanVerticallyScroll="False"
CanHorizontallyScroll="True"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
I think you can use ItemsPanel to change the oriention of listBox. and the borderThickness is also necessary.Hope I can help you. Thx!
<Grid Width="400" Height="150">
<ListBox x:Name="list" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid Width = "80">
<!-- if you want to use border to separate items, HorizontalAlignment="Right";
and if use it as container, HorizontalAlignment="Stretch" -->
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Right"/>
<TextBlock Foreground="Black" Text="{Binding name}" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
I think Chris is on the right lines, but I am sure you need a content presenter in the ItemsPanel template.
<Grid Width="400" Height="150">
<ListBox x:Name="list" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid Width = "80">
<!-- if you want to use border to separate items, HorizontalAlignment="Right";
and if use it as container, HorizontalAlignment="Stretch" -->
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Right">
<TextBlock Foreground="Black" Text="{Binding name}" />
</Border>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
<ContentPresenter/>
</StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Use this code it could help you:
<Grid Width="400" Height="150">
<ListBox x:Name="list" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width = "80">
<Border BorderBrush="Black" HorizontalAlignment="Right" />
<TextBlock Foreground="Black" Text="{Binding name}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Use ItemsPanel property of listbox. try this its work for me.
<Grid Width="400" Height="150">
<ListBox x:Name="list" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid Width = "80">
<Border BorderBrush="Black" HorizontalAlignment="Right" />
<TextBlock Foreground="Black" Text="{Binding name}" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>

Categories