WPF List box with two separated columns - c#

I have to create custom list box the same as on the picture.
I've created UpDown control for each item in list box. But I need to have two columns in list box if will be many items. If it will be two columns, they must be separated as on the picture and each of the column should have border with round corners.
Code for list box is below:
<Style TargetType="{x:Type ListBox}" x:Key="ListBoxService">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate DataType="{x:Type model:Service}">
<Border
x:Name="border"
VerticalAlignment="Center"
BorderThickness="0, 0, 0, 2"
BorderBrush="{StaticResource CommonBackgroundColor}">
<view:ServiceUpDown/>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<UniformGrid Columns="2" HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
</Style>
Thanks for any help.

Not a solution for your exact problem, but maybe this can get you started:
<ListBox
ItemsSource="{Binding Items}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Margin"
Value="0 0 20 0" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
I have set the ListBox' ItemsPanel to a vertical oriented WrapPanel, so once it filled up one "column" in the ListBox it will just wrap into another column.
I have disabled the vertical scrollbar of the ListBoxsince otherwise it would have infinite vertical space, thus the WrapPanelwould never wrap.
This example will wrap the items into additional columns, once all the vertical space of the ListBox has been used. Depending of the vertical size of your listbox and the amount of items there might also be a third or fourth column, when required. You can use the ItemContainerStyle to separate the columns, though this does not resolve the requirement of the rounded borders.

Related

Accurate scrollbar control in an ItemsControl with a VirtualizingStackPanel

I have an Itemscontrol using a VirtualizingStackPanel to display a huge (and growing) list of items:
<ItemsControl Grid.Row="1" Name="ConversationItemsControl" VirtualizingStackPanel.VirtualizationMode="Recycling">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:Message />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The virtualization is working like a charm, but i cannot get the management of the scrollbar right. If I try to programmatically (e.g. on load) scroll to the bottom like i do in non-virtualized StackPanels:
var scrollViewer = VisualTreeHelper.GetChild(ConversationItemsControl, 0) as ScrollViewer;
scrollViewer.ChangeView(null, double.MaxValue, 1f, true);
the scrollviewer tries to scroll to the bottom, but does not do so completely - it always stops a bit before the "real" bottom. This makes sense in a way since VirtualizingStackPanels are using the scroll value to determine which items to render, but it is totally grinding my gears and unacceptable for end users.
How can I scroll to the "real" bottom? What do I have to do if i want to scroll exactly so far down that the top of a certain item is at the top of the viewport (unless the "real" bottom is too close, naturally)?
This is because the built-in ItemsControl class doesn't support virtualization. You can try a ListBox instead, which uses UI virtualization by default.
If you don't want to have selection behaviour, just set:
<ListBox x:Name="lbCustom">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
and then something like:
lbCustom.ScrollIntoView(lbCustom.Items[lbCustom.Items.Count - 1]

Xaml Listview Windows-Universal Horizontal Scroll Mode

I coded a list that has as an Itemsource an Observable Collection, which is of type Grids. So the listview is containing 4 Items (Grids). I want the Grids to be like horizontal next to each other, so I tried this in Xaml.
<StackPanel Orientation="Horizontal">
<ListView ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollMode="Enabled" ItemsSource="{Binding DropGrids, Source={StaticResource view}}" Height="100" x:Name="DropList" RenderTransformOrigin="0.5,0.5" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
<AppBarButton Icon="MapPin" Label="Go!" HorizontalAlignment="Right"></AppBarButton>
</StackPanel>
But when I try scrolling the list to the left it is instantly going back (If you want to simulate is use WGA resolution 4 Inch Emulator) and I can't see the fourth Grid on the screen. How do I fix this?
The ListView.ItemsPanel property I got from this post:
Stackoverflow Post - Horizontal Mode
Not sure on the Grid part in your ListView itemsource, but I blogged about how to create a Horizontal ListView here
http://depblog.weblogs.us/2015/03/25/show-items-scrolling-horizontally-with-listview-in-winrt/
I hope this helps...
The complete style is set as
<Style x:Name="BaseListViewStyle" TargetType="ListView">
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Enabled" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollMode="Disabled"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>

How do I bind the backround row color of a listbox/listview in WP 8.1?

So I made a converter and set up my list box like so:
<ListBox x:Name="QList" Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Status, Converter={StaticResource QColorConverter}}">
<TextBlock Text="{Binding Name}" Foreground="Black" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate >
</ListBox>
However, when I run it, I get just the block right around the text that changes color, not the whole row. How can I make the whole row background change color?
Set ItemContainerStyle HorizontalAlignment to stretch.
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

Stretch GridView to parent control bounds

I have a custom control where I place my SemanticZoom with GridView inside.
The problem is that if GridView has only few items to display then width of the SemanticZoom is less than width of the container. As the result zoom in\out button is placed incorrectly in the middle of the screen.
If there are many items to display, then GridView stretches itself up to the parent control bounds and everything is ok.
How to stretch Semantic zoom (or inner GridView) properly even if there are only few items inside?
Custom container code:
<controls:DataLoader Grid.RowSpan="2" >
<controls:DataLoader.DataContent>
<SemanticZoom x:Name="SemanticZoom" Style="{StaticResource SemanticZoomStyle}" Margin="0,0,0,0" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
<SemanticZoom.ZoomedOutView>
..skipped..
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<GridView x:Name="ZoomedInView"
ItemsSource="{Binding Source={StaticResource GroupedPatients}}"
ItemTemplate="{StaticResource PatientItemTemplate}"
Style="{StaticResource DataGridViewStyle}"
behaviors:SelectionChangedCommandBehavior.Command="{Binding SelectPatientCommand}" Margin="0,0,0,0"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
Background="Yellow">
<GridView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource PatientItemGroupHeaderTemplate}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
</controls:DataLoader.DataContent>
GridView style:
<Style x:Key="DataGridViewStyle" TargetType="GridView">
<Setter Property="IsItemClickEnabled" Value="True"/>
<Setter Property="SelectionMode" Value="None"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
</Style>
</controls:DataLoader>
The correct solution is to use Grid instead of GridView

SemanticZoom Using GridView.Items Instead of GridView.ItemsSource

On the main page of my application I have something like this, showing different subsections and respecting the 80 pixel margin between sections.
<GridView>
<GridView.Style>
<Style TargetType="GridView">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0, 0, 80, 0"/>
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</GridView.Style>
<Grid>
<TextBlock Text="SubTitle1"/>
...
</Grid>
<Grid>
<TextBlock Text="SubTitle2"/>
...
</Grid>
<Grid>
<TextBlock Text="SubTitle3"/>
...
</Grid>
</GridView>
Now I want to add Semantic Zoom to this, so that when I zoom out I see the sub section titles a bit like the Weather app. I have used ItemsSource to do SemanticZoom in the past but how do I do it if I'm placing the actual items straight into my GridView and there is no grouping going on.
EDIT: How are other people handling creating these types of seperate sub sections seperated by 80 pixels? To get SemanticZoom working do both GridViews have to bind to the same collections?
Your GridView above will need to have a name, let's call it ZoomedInGV. This of course becomes the control inside of SemanticZoom.ZoomedInView. Then you'll need to create another GridView, let's call it ZoomedOutGV. Finally, you'll need to create a binding between the two views. The solution should look something like this:
<SemanticZoom>
<SemanticZoom.ZoomedInView>
<GridView x:Name="ZoomedInGV">
...
</GridView>
</SemanticZoom.ZoomedInView>
<SemanticZoom.ZoomedOutView>
<GridView x:Name="ZoomedOutGV" ItemsSource="{Binding ElementName=ZoomedInGV, Path=Items}"/>
</SemanticZoom.ZoomedOutView>
</SemanticZoom>

Categories

Resources