I have the following piece of code
<ItemsControl x:Name="ItemsControl" ItemsSource="{Binding Offers}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<wpf:Card Padding="32" Margin="5" d:DataContext="{d:DesignData }">
<StackPanel Margin="0,0,0,-30" Height="107">
<TextBlock
Style="{DynamicResource MaterialDesignTitleTextBlock}">
<Run Text="Offer " />
</TextBlock>
<TextBlock Text="{Binding CarDescription}" />
<Separator Height="1" Visibility="Hidden" />
<Button Content="Select"
Width="72"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
Margin="0,20,0,0"
Command="{Binding SelectOfferCommand}"/>
</StackPanel>
</wpf:Card>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This produces a bunch of repeated boxes, every has a button. Every time i click the button i want to access current box index (from ItemsControl's ItemsSource) and pass it as a command parameter. Is it possible to do it?
You can pass the current Index of an ItemsControl using the AlterationIndex.
See more info here
Example:
<ItemsControl x:Name="ItemsControl"
ItemsSource="{Binding Offers}"
AlternationCount="1000">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<wpf:Card Padding="32" Margin="5" d:DataContext="{d:DesignData }">
<StackPanel Margin="0,0,0,-30" Height="107">
<TextBlock
Style="{DynamicResource MaterialDesignTitleTextBlock}">
<Run Text="Offer " />
</TextBlock>
<TextBlock Text="{Binding CarDescription}" />
<Separator Height="1" Visibility="Hidden" />
<Button Content="Select"
Width="72"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
Margin="0,20,0,0"
Command="{Binding SelectOfferCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}"/>
</StackPanel>
</wpf:Card>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
May be it will be suitable for you to add index property to each Offer while creating Offers and send this index OnSelectOfferCommand. It will be much easier
ps I think i must explain my answer: My sugestion is not only easier in realisation, but also it is a good practice to seperate busines logic from UI. In this case if UI will be changed, changes will not effect whole ordering process
Related
I'm filling a two WrapPanel with Buttons via DataTemplate but they all align vertically for some reason, what exactly is wrong here?
It doesn't matter if I set the Orientation property or not.
XAML:
<UserControl x:Class="DashboardClient.View.DashboardView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Width="940" Height="640">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="0" Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}},Path=ActualHeight}">
<ScrollViewer VerticalScrollBarVisibility="Auto" DockPanel.Dock="Top" Height="520" Margin="5">
<WrapPanel>
<ItemsControl ItemsSource="{Binding Dashboards}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="120" Height="120" Margin="5" Command="{Binding DataContext.DashboardCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" CommandParameter="{Binding}">
<TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Text="{Binding Name}" />
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Width="120" Height="120" Margin="5" Command="{Binding DashboardAddCommand}" Content="+" FontSize="100" />
</WrapPanel>
</ScrollViewer>
<StackPanel Height="100" Margin="5">
<Label>Dashboardname:</Label>
<TextBox Text="{Binding SelectedDashboard.Name}" />
<RadioButton Content="Sichtbar" Margin="0 10" IsChecked="{Binding SelectedDashboard.IsVisibleOnDashboard, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Dashboard löschen" Command="{Binding DashboardRemoveCommand}" />
</StackPanel>
</DockPanel>
<StackPanel Grid.Column="1" Margin="0">
<ScrollViewer VerticalScrollBarVisibility="Auto" Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StackPanel}},Path=ActualHeight}">
<WrapPanel>
<ItemsControl ItemsSource="{Binding SelectedDashboard.DashboardItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="200" Height="120" Command="{Binding DataContext.DashboardItemCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" CommandParameter="{Binding}" Margin="10">
<TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Text="{Binding Name}" />
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Width="200" Height="120" Content="+" FontSize="100" Command="{Binding DashboardItemAddCommand}" Margin="10" />
</WrapPanel>
</ScrollViewer>
</StackPanel>
</Grid>
</UserControl>
This is what the WrapPanel looks like:
The Add Button is always cut off somehow, too.
If you want to put the children of the ItemsControl horizontally in a WrapPanel, you need to tell the ItemsControl to use a WrapPanel for its children via an ItemsPanelTemplate:
<WrapPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding Dashboards}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Width="120"
Height="120"
Margin="5"
Command="{Binding DataContext.DashboardCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"
>
<TextBlock
TextWrapping="Wrap"
HorizontalAlignment="Center"
Text="{Binding Name}"
/>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button
Width="120"
Height="120"
Margin="5"
VerticalAlignment="Top"
Command="{Binding DashboardAddCommand}"
Content="+"
FontSize="100"
/>
</WrapPanel>
I don't know what you want to do with the button. My guess is that you want it to the right of the ItemsControl, and I aligned it to the top because that makes more sense to me.
Instead of
<ScrollViewer>
<WrapPanel>
<ItemsControl ItemsSource="{Binding Dashboards}">
<ItemsControl.ItemTemplate ... />
</ItemsControl>
<Button Content="+" ... />
</WrapPanel>
</ScrollViewer>
You can use
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Dashboards}">
<ItemsControl.ItemTemplate ... />
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button Content="+" ... /> <!-- A -->
</ScrollViewer>
<Button Content="+" ... /> <!-- B -->
WrapPanel is moved inside ItemsControl to layout dashboards.
You can put button somewhere else (same as #EdPlunkett I don't have a good idea where to put it): A - will let you to scroll button together with dashboards and B will keep button fixed, disregards scrolling.
I have a slightly extraordinary request ;-)
I'd like to develop an ItemsControl with a "Previous" Control and a "Next" Control. Like this bound to an arbitrary ViewModel:
<controls:PagedItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="system:String">
<Border Background="Gray" Margin="5">
<TextBlock Text="{Binding}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<controls:PagedItemsControl.PreviousControl>
<Button Content="Previous" Command="{Binding PreviousCommand}" />
</controls:PagedItemsControl.PreviousControl>
<controls:PagedItemsControl.NextControl>
<Button Content="Next" Command="{Binding NextCommand}" />
</controls:PagedItemsControl.NextControl>
</controls:PagedItemsControl>
In the example I passed 2 buttons controlled by the ViewModel's commands. It would be awesome if somebody could tell me how to listen to the Control.IsEnable state and show the PreviousControl as first item if enable and the the NextControl as last item if enable.
Thank you
Have a look at the following XAML. We cannot add elements to ItemsPanel while using ItemsSource. But we may try to build a tricky collection which consists of ItemsSource and additional elements. Unfortunately CollectionContainer unable to bound to Items directly. Lucky that good guys already found a solution for this case.
<Grid>
<Grid.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
</Grid.Resources>
<TextBlock Name="TrickyBinder"
Tag="{Binding Items}"
Visibility="Collapsed"/>
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="system:String">
<Border Background="Gray" Margin="5">
<TextBlock Text="{Binding}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsSource>
<CompositeCollection>
<CollectionContainer>
<CollectionContainer.Collection>
<col:ArrayList>
<Button Content="Previous" Command="{Binding PreviousCommand}" Visibility="{Binding Path=IsEnabled,RelativeSource={RelativeSource Self},Converter={StaticResource BoolToVisibilityConverter}}" />
</col:ArrayList>
</CollectionContainer.Collection>
</CollectionContainer>
<CollectionContainer Collection="{Binding Path=Tag,Source={x:Reference TrickyBinder}}"/>
<CollectionContainer>
<CollectionContainer.Collection>
<col:ArrayList>
<Button Content="Next" Command="{Binding NextCommand}" Visibility="{Binding Path=IsEnabled,RelativeSource={RelativeSource Self},Converter={StaticResource BoolToVisibilityConverter}}" />
</col:ArrayList>
</CollectionContainer.Collection>
</CollectionContainer>
</CompositeCollection>
</ItemsControl.ItemsSource>
</ItemsControl>
</Grid>
Hope this helps!
I have the following XAML code:
<StackPanel Background="White" Margin="267,207,0,44" Grid.ColumnSpan="2">
<ScrollViewer Margin="30,30,0,30" Height="444">
<ItemsControl Name="ListCountries">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,10,0" Width="100">
<TextBlock Text="{Binding Key}" Foreground="Red" />
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,10,0,0">
<TextBlock TextWrapping="Wrap" Text="{Binding title}" Foreground="Black" />
<TextBlock TextWrapping="Wrap" Text="{Binding desc}" Foreground="Gray" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
I set the itemSource of the itemsControl named ListCountries, with a IEnumerable> and it prints a list of titles, followed by a list of objects of the OtherClass.
My problem is that , the columns that are filled sometimes are bigger than the height of the Stackpanel that they are inserted to, i want to be able to split my inner list of into columns.
as you can see in the image, Belgium country gets splited into 2 columns
right now all my countries are single column with vertical scroll.
You should use a GridView for this. Here's some code slightly modified from a Grid app in Visual Studio
<GridView
x:Name="itemGridView"
Grid.RowSpan="2"
Padding="116,137,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
SelectionMode="None"
Height="600">
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="200">
<TextBlock Text="{Binding Description}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="60" Margin="15,0,15,0"/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" Style="{StaticResource SubheaderTextBlockStyle}" TextWrapping="NoWrap" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
Here's a screenshot of what this looks like, with sample data
Ok, this is driving me nuts! I have spent a good half of my day working on this problem. I am using a XAML based Windows 8.1 app, and essentially I am trying to implement some drag and drop functionality between groups in a GridView. So far everything has been working, except when I try to "drop" an item into a new group. After way to much time, I have narrowed it down to the "drop" event not being fired for the GroupStyle.Panel VariableSizedWrapGrid. I was trying to follow something along the lines of this webpage.
I for the life of me cannot figure out why it won't fire. I have tried testing other drop events throughout my gridview, and they all seem to be working as expected.
Below is the code I currently have in place:
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Grid.RowSpan="2"
Padding="116,137,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}, Mode=TwoWay}"
SelectionMode="None"
CanDragItems="True"
DragItemsStarting="itemGridView_DragItemsStarting"
IsSwipeEnabled="true"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate>
<VariableSizedWrapGrid HorizontalAlignment="Left" Width="250" Height="250">
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="splash"/>
</Border>
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding Path=Name }" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="60" Margin="15,0,15,0"/>
</StackPanel>
</VariableSizedWrapGrid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid GroupPadding="0,0,70,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.GroupStyle>
<GroupStyle HidesIfEmpty="False">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<VariableSizedWrapGrid Margin="0,0,0,2">
<Button Foreground="{ThemeResource ApplicationHeaderForegroundThemeBrush}"
AutomationProperties.Name="Group Title"
Style="{StaticResource TextBlockButtonStyle}"
Click="Button_Click">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="0,-11,10,10" Style="{StaticResource SubheaderTextBlockStyle}" TextWrapping="NoWrap" />
<TextBlock Text="{StaticResource ChevronGlyph}" FontFamily="Segoe UI Symbol" Margin="0,-11,0,10" Style="{StaticResource SubheaderTextBlockStyle}" TextWrapping="NoWrap" />
</StackPanel>
</Button>
</VariableSizedWrapGrid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Drop="VariableSizedWrapGrid_Drop" AllowDrop="True"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
I really hope someone out there can see my error! I'm sure it is something simple, but I just need someone to point out the obvious. :)
Had the same problem, then found this example:
How to drag item between groups in grouped gridview
I tried to use StackPanel as ItemsPanel of GridView, worked for me. Try to use StackPanel instead of ItemsWrapGrid for your GridView.
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
Still can't understand this behavior, any ideas?
here is my code
<phone:LongListSelector ItemsSource="{Binding MovieTimeInDetailItems}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="24,0,0,12">
<TextBlock Text="{Binding Theater}" FontSize="34"/>
<ListBox ItemsSource="{Binding TimeItems}" HorizontalAlignment="Stretch" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="115" Margin="0,0,0,0">
<TextBlock Text="{Binding Time}"
TextWrapping="Wrap"
HorizontalAlignment="Left"
VerticalAlignment="Top"
FontSize="26"
Foreground="{StaticResource PhoneSubtleBrush}"/>
<Border Margin="92,0,0,0" HorizontalAlignment="Left" Width="{Binding Width}" Height="25" BorderThickness="1.5,0,0,0" BorderBrush="{StaticResource PhoneSubtleBrush}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
In each LLS item contains a Listbox which display time list.
my question is ...
Can I display a time list without Listbox ? It seems Listbox cause the low performance.