How UniformGrid work with infinite size - c#

For example we have a ListBox with a UnidormGrid like a ListBoxPanel.
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}, Path=Items.Count}"></UniformGrid>
<!--<cntr:StackGrid Orientation="Horizontal" Direction="Normal"/>-->
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<Button>1</Button>
<Button>2</Button>
<Button>3</Button>
<Button>4</Button>
</ListBox>
ListBox will give a infinite size to UniformGrid, but there is no any errors. UniformGrid will use only a visible size. How it do that? It will help me in bulding my own panel.
P.S. I know, that i can to disable ScrollView in ListBox and my panel will get a visible size.

As far as I know, the UniformGrid derives its cell size by the largest child it is displaying. It breaks the content to a new line when either its width or height is exceeded, according to the Orientation property. By default, it is set to Horizontal.
Which leads me to your question: why do you think that it has an infinite width? Sure, the ListBox contains a ScrollViewer in its default control template, but in my opinion it only provides vertical infinite space for the panel (horizontally, it is constrained to the width of the list box), which allows breaks for the default uniform grid to happen.
If you have any further questions, please feel free to ask.

Related

Single Row Horizontally Scrolling/Swipeable GridView

I wanted a single-row GridView that can be scrolled horizontally both with mouse and touch swipe. The GridView is to present images through binding so that a single image will be selected from an array of images.
Everything works fine (binding, image selection, etc.) except that the horizontal scroll doesn't work. The XAML code is shown below.
What am I missing?
<GridView x:Name="IconGridView"
Grid.Row="0"
Margin="8,12"
DataContext="{x:Bind IconManagerObj}"
DoubleTapped="{x:Bind IconGridView_DoubleTapped}"
IsItemClickEnabled="True"
IsSwipeEnabled="True"
ItemsSource="{Binding Path=IconImageInfo}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollMode="Disabled"
SelectionMode="Single"
Tapped="{x:Bind IconGridView_Tapped}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="4,8"
HorizontalAlignment="Center"
BorderBrush="{ThemeResource SubtleBlueBrush}"
BorderThickness="1">
<Image Width="150" Source="{Binding IconImage}Stretch="Uniform"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
You have everything right but the Orientation for the ItemsWrapGrid must be Vertical in order to have an Horizontal ScrollViewer.
The documentation here https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemswrapgrid.aspx explains that:
When the value is Vertical, the grid adds items in columns from top to bottom, then wraps from left to right. Columns of items scroll or pan horizontally.
Juan Pablo Garcia Coello's answer put me on the right track but didn't work without an additional setting. The crucial thing I found out through trial was setting the Height for GridView.
Height must be set enough for a single row elements to display but not high enough to allow a second row. For image height of 100 I set this arbitrarily to 140 and works great.
ScrollViewer.VerticalScrollMode must be Disabled
ScrollViewer.HorizontalScrollMode must be Auto or Enabled
ScrollViewer.HorizontalScrollBarVisibility must be Auto or Enabled
The most crucial, as Juan indicated, the ItemsWrapGrid Orientation must be Vertical (sounds counterintuitive but works!)
I have marked Juan's as answered as it provides a complete answer with this one, due to the fact that I couldn't have quickly figured out a complete answer without the Orientation being set Vertical -- a rather counter-intuitive setting if you ask me but now I get it.

WP8: ListBox last row won't remain scrolled into view

When vertically scrolling into view, I can pull the last row into view, but on releasing the drag, the last row springs back (partially) out of view. I think inaccuracy of measure can be attributed to a grid that I'm using as the listbox's header but I'm currently unable to fix this to that they work together correctly.
<Border>
<StackPanel>
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Auto">
<StackPanel>
<Grid x:Name="_headers"/>
<ListBox x:Name="_dataGrid"/>
</StackPanel>
</ScrollViewer>
</StackPanel>
</Border>
**Update
This example removes the scroll and also suffers from the same truncated row problem as the example above. The header grid row also doesn't scroll horizontally with the listbox rows which is an even bigger problem for my solution.
<Border>
<StackPanel>
<Grid x:Name="_headers"/>
<ListBox x:Name="_dataGrid"/>
</StackPanel>
</Border>
It's because you put ScrollViewer inside StackPanel. StackPanel doesn't limit control's size so the ScrollViewer can grow forever and never scroll properly. Its size must be limited. Grid can do it perfectly (if only the height of the row is set to *, not Auto).
Also, in my opinion you shouldn't put ListBox inside ScrollViewer, because ListBox already has its own scroll feature.
Never ever use a ListBox inside a ScrollViewer, you will run into scrolling conflicts.
As far as I can see, you need to add a header to your list. LongListSeelctor might be the best option, since it has got a Header property (also Footer):
See: http://www.geekchamp.com/articles/the-new-longlistselector-control-in-windows-phone-8-sdk-in-depth

Need advice on customizing ListBox template

I have a ListBox of CheckBox values, the number of values vary from time to time, it can be 10, 15, 100, etc..
I would like to customize the way the values are displayed. Currently, if I have 50 values, they are all displayed vertically, just one column.
I would like to have it such that, 1 column will have a maximum of 10 values, and I am able to scroll horizontally to view the values at other columns.
I tried using ItemsPanelTemplate with StackPanel orientation horizontal, but well, all values are now in 1 row.
Please advice.
Thanks!
You could try changing the panel used by your ListBox to a WrapPanel instead. Set its Orientation to Vertical, then size the height of the ListBox so it fits 10 items in each "column" before starting a new column.
<ListBox Height="..."
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
If you want 10 items in each column but don't want to explicitly set the height of the ListBox then the only solution I can think of is writing a custom Panel.

WPF ListBox Auto Width Changes Incorrectly When DataTemplate Has Visibility Bindings

I have a ListBox docked to the left of a window whose width should size to it's contents. When I scroll the listbox, it's width wobbles and becomes wider than it should be. Essentially what I think is happening is that the ListBox calculates the size of all it's children to determine it's own size, but only seems to evaluate visibility bindings for controls that are actually on the screen (presumably for performance reasons). The result is that it calculates the size of it's off-screen children incorrectly, reserving space for hidden controls.
If there are fewer items in the list than the window height (and thus no scrollbar), the list is always the correct width, and it always snaps to the correct width when you scroll to the top or bottom. It's only whilst the scrollbar is positioned somewhere inbetween that the width is wrong.
I've been wrestling with this problem all evening, trying various refactorings like using a DataTemplateSelector to abstract away the need for visibility bindings but I've ended up with really dirty workarounds I'm not happy with. I'd like to solve the actual problem at hand rather than dodge it. Any pointers would be much appreciated.
In the following example, the list appears to size itself to the width of both Foo and Bar. Changing the StackPanel orientation causes it to size to the width of whichever is longer out of Foo and Bar. Hope that makes sense.
<ListBox ItemsSource="{Binding Widgets}" DockPanel.Dock="Left">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Visibility="{Binding ShowFoo, Converter={StaticResource BoolToVisConverter}}" Text="{Binding Foo}" />
<TextBlock Visibility="{Binding ShowBar, Converter={StaticResource InverseBoolToVisConverter}}" Text="{Binding Bar}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This effect what you're describing does not have to do with the visibility bindings.
Essentially what I think is happening is that the ListBox calculates
the size of all it's children to determine it's own size, but only
seems to evaluate visibility bindings for controls that are actually
on the screen (presumably for performance reasons). The result is that
it calculates the size of it's off-screen children incorrectly,
reserving space for hidden controls.
This sounds correct to me. It's done for performance reasons. Also known as virtualization of ListBox. The other controls inherit this too, such as DataGrid.
In order to get rid of it, you can switch out VirtualizingStackPanel with the usual stackpanel:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
You might, or might not suffer the performance penalty, if you have massive amount of items, but that's the life. If you do not like this, I suggest you not to have this requirement in the first place.

make horizontal scrollable custom calendar

I want to make calendar in windows phone 8 using XAML/c#. It should like horizontal bar that has 7 days fit to screen. User can scroll these dates like on phone screen there are 1 to 7 dates and user can scroll to view more dates. If user tap on any date then its color should be changed. I was trying to implement longlistselector and listbox but could do successfully. I am newbie. please help.
Thanks
ongListSelector doesn't allows you to change scroll orientation. In other controls like the ListBox you can specify the property ItemsPanel to use a StackPanel with horizontal orientation. But that property is not available in LongListSelector (i don't know exactly the reason, but i think it might be something related with the complex grouping, jump list capabilities of the LongListSelector.
If you need to make an horizontal list and you don't need to group your data, you can replace the LongListSelector with a ListBox and use the ItemsPanel property to specify a horizontal stackpanel.
So, no issues.
You can of course use the ListBox instead of LongListSelector.
You can have it horizontally scrollable as follows:
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Auto">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Your control... />
</DataTemplate>
</ListBox.ItemTemplate>

Categories