I do not know what the container/control im looking for would be called, so I cannot really search for it.
Add More of Same Usercontrol Usercontrol
Clicking on + would add a new instance of My Usercontrol to the right of the existing ones
Clicking on X would dispose the usercontrol that was clicked
I'm not really looking for a tab control that would put each new instance on a new tab, but if there is nothing else then it might do.
The design is not to be as shown in the image obviously, the image just illustrates the basic idea
Any keyword/name suggestions or links to existing implementations?
e.g. Maybe there is a style that turns a ListBox into something suitable?
I would use an ItemsControl and customize it's ItemsPanelTemplate to be whatever you want.
ItemsControls are meant for iterating through a collection of objects, and displaying them in whatever form you want. I wrote some simple code samples of them here if you're interested, or here's another quick example:
<DockPanel x:Name="RootPanel">
<Button Style="{StaticResource AddButtonStyle}"
DockPanel.Dock="Right" VerticalAlignment="Center"
Command="{Binding AddItemCommand" />
<ScrollViewer>
<ItemsControl ItemsSource="{Binding MyCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<local:MyUserControl />
<Button Style="{StaticResource RemoveButtonStyle}"
Command="{Binding ElementName=RootPanel, Path=DataContext.RemoveItemCommand}"
CommandParameter="{Binding }"
HorizontalAlignment="Left" VerticalAlignment="Top" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
Your ItemsControl would be bound to an ObservableCollection of objects, and your Add/Remove buttons would simply add/remove items from that collection. Since it is an ObservableCollection, it will notify the UI when the collection gets changed and automatically update.
You can indeed use a ListBox and set its ItemTemplate and ItemsPanelTemplate:
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Of course, your ItemTemplate would be a reference to your control.
You could look at something called a carousel control which uses a list of objects behind it and displays them similarly to itunes. This could be a bit over the top but is one solution. An example can be seen here
If this is too advanced for your needs, could it be as simple as a stackpanel with a scrollbar which is bound to a list of your user controls?
Related
i am trying to make a XAML with wrapping list view, or is it a grid, or table. I am just not sure. Please take a look at the image. How would i go about formatting my "list" that needs to wrap around the view, can someone please give me sample XAML, as i have no idea how to realize how to make this view.
It seems i need to use a ListView inside a Wrappanel of some sort? The data is dynamic, such as i can have any number of key/value pairs as seen here (open, high, lose, close, etc...) so keep in mind the pairs can have any number and they need to wrap around the control/window.
Any idea how to define such a XAML?
Thanks.
I've since figured it out. I'm using an itemcontrol instead of a list and put a wrappanel. Like this.
<ItemsControl ItemsSource="{Binding DataItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Width="100" Text="{Binding KeyText}"></TextBlock>
<TextBlock Width="100" Text="{Binding ValueText}"></TextBlock>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
SOF Tribe,
I have a request for the identity of a flow container into which I can pour an indeterminate number of dynamically created XAML buttons. Said buttons should wrap the text as closely as possible (I think I have a template for this). But the buttons should wrap like a gridview, but run like a stackpanel. Does anyone know a container that will allow me to accomplish what the image portrays?
Currently, for the existing image below, I'm using a gridview, but the gridview sets a specific width but does flow unevenly. A stackpanel has the desired end-to-butt style but won't wrap. So, any ideas?
There is what is called the UniversalWrapPanel made by Greg Stoll. So, that's the direction I'll be taking. Now however, I've got the last little bit to tackle. How to get the bound data to respect the parent container's ability to wrap content and not just stack it up in a vertical column.
The below XAML gives me the below image result which is not quite what I want. Statically added buttons work just fine to the UniversalWrapPanel. But trying to get a binding and ItemsSource to work, well, that's beyond me at this time.
<support:UniversalWrapPanel Orientation="Horizontal" Background="White">
<ItemsControl x:Name="GridViewRecipients" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource ButtonLozengeStyle}" Content="{Binding FullName}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</support:UniversalWrapPanel>
OK, so a bit more searching and I found this:
http://www.visuallylocated.com/post/2015/02/20/Creating-a-WrapPanel-for-your-Windows-Runtime-apps.aspx
and so here is the correct way to reference the UniversalWrapPanel within the ItemsControl:
<ItemsControl x:Name="GridViewRecipients" ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<support:UniversalWrapPanel Orientation="Horizontal" Background="DodgerBlue"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource ButtonLozengeStyle}" Content="{Binding FullName}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
For the result of:
I have an ItemsControl nested inside a ListBox.ItemTemplate. The top ListBox is data-bound to an ObservableCollection. The collection is essentially a Purchase which contains Formulae which in turn contain individual products.
Now, if an individual product inside a formula is clicked, I would like it to be deleted from its formula. So, in the event handler, I should be able to determine the product's position using:
var index = [theItemsControl].ItemContainerGenerator.IndexFromContainer((sender as Button).TemplatedParent);
However, in my event handler, I do not how how to find the containing ItemsControl. I cannot give it a fixed name, since it is itself a part of a ListBox.ItemTemplate, meaning there will be multiple instances.
This is my XAML, stripped of any style-related stuff:
<ListBox x:Name="lbBasketFormulae" ItemsSource="{Binding Path=Purchase.Formulae}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<!-- Formula Title -->
<StackPanel Orientation="Horizontal">
<Label Width="30" Content="{Binding Path=Quantity}"></Label>
<Label Content="{Binding Path=FormulaType, Converter={StaticResource formulaTypeToNameConverter}}"></Label>
</StackPanel>
<!-- Formula Products -->
<ItemsControl ItemsSource="{Binding Path=Products}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button x:Name="bnBasketFormulaProduct" HorizontalContentAlignment="Left" Content="{Binding Path=Name}" Click="bnBasketFormulaProduct_Click">
<Button.Template>
<ControlTemplate TargetType="Button">
<TextBlock Text="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
So, my question is: How do I find the position of my product inside my formula and the position of that formula inside the purchase, so that I can remove it from the ObservableCollection? (Changing the collection should then automatically reflect to the UI since it is data-bound.)
Many thanks in advance for any advice or hints!
Regards,
Chris
It is true that you should be able to do it via the viewmodel. But if you want you could use:
VisualTreeHelper.GetParent(myUserControl);
The answer is you don't find any positions of anything using ItemContainerGenerator.IndexFromContainer. Your problem is clearly taking place inside ViewModel and therefore you should seek for selected item or whatever inside your ViewModel and not in ListBox or code behind of Window.
Therefore I suggest you to create a proper ViewModel with proper Bindings.
I´m filling a listbox with a specific data, the code works fine, but I need to add a scrollviewer to the listbox because there are many elements inside, I tried to use a ScrolViewer and put inside the listbox, but doesn't work, here is the code
<StackPanel x:Name="Sites" Grid.Row="1" Orientation="Vertical">
<ListBox x:Name="ListSites" >
<ListBox.ItemTemplate>
<DataTemplate>
<Button Width="460" Height="120" Click="click" Name="btn">
<Button.Content>
<StackPanel Orientation="Vertical" Height="100" Width="460">
<TextBlock Width="460" Name="txtname" FontSize="22" Text="{Binding name}" Height="40" Foreground="CadetBlue" />
<TextBlock Width="460" Name="txtUrl" FontSize="22" Text="{Binding Url}" Height="60"/>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
I fixed it, simply adding the Height property in the ListBox control
If the ListBox is not given infinite space for height then it should automatically scroll when items overflow its boundaries. For instance, if the second Grid row outside your stackpanel has explicit or 'star' height set, the scrollbar in the listbox will show up automatically.
See also: Silverlight: Difficulty with ScrollViewer
You shouldn't need to add a ScrollViewer to your ListBox. It will start scrolling when it runs out of room.
However, because you've put the ListBox inside a StackPanel it won't ever think it's run out of room because the StackPanel grows infinitely in the direction of it's orientation to accommodate its contents.
You'll need to use a different container for your ListBox.
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
I have a Silverlight user control that contains an ItemsControl that renders a StackPanel containing another user control for each item in the data source, the XAML is as follows:
<Grid x:Name="LayoutRoot">
<ItemsControl ItemsSource="{Binding}" x:Name="ValuesItemSource">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel x:Name="ValuesPanel" Background="Transparent" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:MyCustomControl DataContext="{Binding}" x:Name="Value" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
How would I reference the collection of MyCustomControls (Values) in the code behind of this user control?
(I have an event handler registered in the code behind of this control and I want to invoke a method of each "MyCustomControl" when the event fires)
You need to ask the itemsControl.ItemContainerGenerator for this. See here for an example.