I'd like to display basically a matrix of buttons, the number of buttons change in runtime.
My problem is that I want them to be next to each other to fill up all the space I give them. I thought WrapPanel is the perfect way to do that but it puts the buttons under each other and I have no idea how to solve it.
<Grid>
<WrapPanel Width="250" Height="50" Orientation="Horizontal" Margin="543,442,73,162" >
<ItemsControl ItemsSource="{Binding States}" >
<ItemsControl.ItemTemplate>
<DataTemplate >
<Button Width="50" Height="25" Content="{Binding StateName}" Padding="0" ></Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</WrapPanel>...</Grid>
States is a list of Items that contains a name and a ID number. If i want to add or remove buttons I modify the list. So the buttons appear but in vertical order and they go beyond the limits of the WrapPanel so if it is not big enough only some appears. They only use 50 width from the 250 and more then the 50 height. In this case if I put 5 buttons in it only shows 2 of them.
Don't wrap ItemsControl inside WrapPanel. Instead set it as ItemsPanel of ItemsControl.
<ItemsControl ItemsSource="{Binding States}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="50" Height="25" Content="{Binding StateName}"
Padding="0"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Related
I've written a code example below:
<StackPanel>
<TextBlock>Appointments today</TextBlock>
<ItemsControl ItemsSource="{Binding Appointments}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<controls:CalendarMonthDayEventsItemsPanel OutsideViewportCount="..." />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border>
<TextBlock Text="{Binding Title}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Orientation="Horizontal">
<TextBlock>+</TextBlock>
<TextBlock Text="{Binding ......}" /> <!-- Should show number of items in ItemsControl that are outside view, using CalendarMonthDayEventsItemsPanel.OutsideViewportCount -->
<TextBlock>more items</TextBlock>
</StackPanel>
</StackPanel>
I Created a custom Panel, the CalendarMonthDayEventsItemsPanel, and I use that panel as the itemspanel of the ItemsControl. In the panel's layout code, I determine how many items (panel childs) are outside the bounds of the panel. The property OutsideViewportCount contains the number of items that are outside of the visible bounds of the CalendarMonthDayEventsItemsPanel.
Now I want to show the value of OutsideViewportCount in a TextBlock that's below the ItemsControl.
This means I have to create some kind of binding, but everything I tried doesn't work.
Does someone have a solution or a better approach to achieve the same result?
Maybe you can make use of Tag property of ItemsPanel to relay the value of ItemsPanel as a workaround.
<ItemsControl x:Name="A"
ItemsSource="{Binding Appointments}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:CalendarMonthDayEventsItemsPanel OutsideViewportCount="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=Tag, Mode=OneWayToSource}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
...
</ItemsControl>
<StackPanel Orientation="Horizontal">
<TextBlock>+</TextBlock>
<TextBlock Text="{Binding ElementName=A, Path=Tag, Mode=OneWay}"/>
<TextBlock>more items</TextBlock>
</StackPanel>
How to do drag and drop with elements in ItemsControl?
I turn AllowDrop and CanDrag in true but nothing works.
<ItemsControl Visibility="Collapsed" ItemsSource="{Binding MyItems}" Margin="0,3,0,0" Padding="5,0,0,0" CanDrag="True" AllowDrop="True">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid MaximumRowsOrColumns="3" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border CanDrag="True" AllowDrop="True" Background="{Binding Color}" Height="{Binding Height}" Width="{Binding Width}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This does not work on the phone. I know about listView and GridView. I do not need Reorder Mode. I need a table where you can drag and drop items, and replace each other. 1 > 5 and 5 > 1 places. Swap elements of the first to the fifth, and the fifth on the first!
I have thought of doing something like CanvasTabelView. I do not know whether it is real!
I am using a WPF UniformGrid to bind alist of items and the xaml is like this
<ListBox Name="lviewSearch" ItemsSource="{Binding SearchSettingsCollection}" SelectionMode="Multiple">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<ItemsControl Margin="3" Padding="5">
<DockPanel>
<Label Content="{Binding Label}" HorizontalAlignment="Stretch" Cursor="Hand" />
</DockPanel>
</ItemsControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But if the no of items is less then the spacing between rows is too much like this
http://i.stack.imgur.com/Xr5qy.png
How can i ireduce thi s?
Like people said, your UniformGrid has too much vertical space so it expands the rows to take up all that space (stretches).
What you need to do is prevent this default behavior of stretching by setting
VerticalAlignment="Top"
The whole point of the UniformGrid is that the size of cells is uniform and therefore the same size. If you only have a small number of rows compared to the vertical space then each row is going to be pretty tall. Conversely if you have many rows and little vertical space then each row becomes tiny. If this is not an appropriate appearance then you need to use a different method of laying out.
Without knowing much more about the visual design it becomes impossible to recommend a possible alternative. Is the ListBox always the same size or will it vary in height? Does the number of displayed results vary or stay constant? All these change how you might achieve the required result.
One simple solution is to use grid outside Listbox. Set row height as auto. Now Uniform grid will take minimum space as required.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Name="lviewSearch" ItemsSource="{Binding SearchSettingsCollection}" SelectionMode="Multiple">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<ItemsControl Margin="3" Padding="5">
<DockPanel>
<Label Content="{Binding Label}" HorizontalAlignment="Stretch" Cursor="Hand" />
</DockPanel>
</ItemsControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I have the following XAML which produces a vertical output of several TextBlocks and ListBoxes, however I want to change it so that it will go horizontally.
<StackPanel>
<TextBlock Margin="5" Text="Collated Results" FontWeight="Bold"
VerticalAlignment="Center" DockPanel.Dock="Top"/>
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto" CanContentScroll="True">
<ItemsControl x:Name="lstCollatedSensorData">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Margin="5" Width="100" Text="{Binding Name}"/>
<ListBox Margin="5" Width="100"
ItemsSource="{Binding CollatedResults}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
The Textbox and Listbox in the StackPanel show correctly individually, however, each iteration is placed on top of each other, where I want them to be placed side by side horizontally. I have tried inserting WrapPanels in various locations without success, so there is obviously something that I am missing. It almost seems like the ScrollViewer is forcing the ItemsControl to be vertical rather than horizontal.
Put a stackpanel with orientation horizontal in the ItemsControl's ItemsPanel
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
Try setting Orientation on the stackpanel like so
StackPanel Orientation="Horizontal"
I am trying to do an interface in WPF where a list of item is displayed, taking as little vertical space as possible:
My instinct was to use an ItemsControl to bind my list, and to put the UI for each item into a WrapPanel. Unfortunately by default, each item starts at a new line regardless of the window's size. Adding a StackPanel with Orientation="Horizontal" makes all items in a single line, regardless of the size...
<!--<ScrollViewer Grid.Row="0" Grid.Column="0"
VerticalScrollBarVisibility="Auto">-->
<ItemsControl Margin="0,4" ItemsSource="{Binding Path=Watchers}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type Core:Watcher}">
<WrapPanel Orientation="Horizontal">
<TextBlock Margin="0,2" Text="{Binding Path=Name}"
Width="250px" />
<TextBox Text="{Binding Path=Value, Mode=OneWay}"
Width="300px">
</TextBox>
</WrapPanel>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
<!--</ScrollViewer>-->
Any pointers?
Bonus point: Where should I add a ScrollViewer in order to have the behavior shown in my mockup?
Thanks a lot!
The WrapPanel has, as well as the StackPanel, an Orientation property, which defaults to Vertical. So your list should wrap (assuming you have enough space at hand) if your ItemsPanelTemplate looks like this:
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
About the ScrollViewer:
The desired behavior should be achieved by defining it like follows (not tested though, and I omitted all for this example unnecessary stuff):
<ScrollViewer HorizontalAlignment="Stretch">
<ItemsControl MinWidth="550" Width="{Binding ActualWidth, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollViewer}}}" />
</ScrollViewer>
I think you want the WrapPanel in the ItemsPanel and the StackPanel in the ItemTemplate.
why not use the WrapPanel as ItemsPanelTemplate?
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
as long as the items have space to the left they would be arranged horizontal.