I'm not sure about the best way to implement this in WPF, so I'll state my problem first.
I have a collection of frames. Each frame has two images. Let's say I have 10 frames giving a total of 20 images. I want to show the images at the bottom of the screen organized like a film strip - 2 rows and 10 columns. When the user clicks on one of this images or uses the arrow, it should become selected and the selected image information will be used somewhere else in the application.
I've implemented it as a ListBox with ItemsSource bound to my viewmodel's Frames collection (an observablecollection). In the DataTemplate of the ListBox, I've created a grid with two rows, each one containing a Image control. The one on row 0 is bound to TopImage (a property of my Frame class) and the bottom one is bound to BottomImage.
All this work, but the problem is that when I use the arrows, the whole frame (item) gets selected. How do I select each image in the datatemplate individually?
OR
Is there a better way to implement this>
You have two problems:
You want to separate the selectability of the upper and lower images in a frame
You want the arrow keys to be able to navigate images in two dimensions
If you did not have the arrow key requirement, then you could solve the first problem by nesting ListBox objects inside a parent ItemsControl. But then the arrows only do the right thing within a ListBox. To address that requires a different approach.
Here is a 2x2 grid data-bound to a four-element collection of images. Here we use the little-used UniformGrid to cause the collection to wrap after so many columns. Since we're using an ItemsControl, we lose automatic selection support but we get it back by making the Image control the content of a Button.
<Grid>
<Grid.Resources>
<x:Array x:Type="sys:String" x:Key="sampleData">
<sys:String>http://thecybershadow.net/misc/stackoverflow.png</sys:String>
<sys:String>http://thecybershadow.net/misc/sourceforge.png</sys:String>
<sys:String>http://thecybershadow.net/misc/stackoverflow.png</sys:String>
<sys:String>http://thecybershadow.net/misc/sourceforge.png</sys:String>
</x:Array>
</Grid.Resources>
<ItemsControl ItemsSource="{StaticResource sampleData}" Focusable="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button>
<Button.Content>
<Image Source="{Binding}"/>
</Button.Content>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
The net effect is a 2x2 grid of images that you can freely arrow around between. You can use styling to make the button aspect less button-like without losing focusability. So bind all twenty images to this view, first the top ten and then the bottom ten. You can also bind the column count from the same data source.
Related
I am doing one project where I want display the office floor with two thousnads seats which will be user interactive and will be inside the wpf Viewport2DVisual3D and all the seats(cells) will have stack panel with image which is bound with data base items from table) I will be using scroller and zoomer for moving in the screen.My question is whetehr I have to use Grid view or List view(with conrol templates) for this purpose considering the performance and maintenance or is there any other option to do this. I am new to WPF please help me ?
A Canvas control can be used to place items with arbitrary pixel coordinates, maybe that could be usefull?
<Canvas>
<Stackpanel Canvas.Left="10" Canvas.Right="10"></Stackpanel>
<Stackpanel Canvas.Left="20" Canvas.Right="20"></Stackpanel>
</Canvas>
Here's my issue: I have a wrapper class that contains sets of lists that contain 15 images each. I want to bind a central StackPanel to a method that actually modifies the same StackPanel that was passed to it and adds child StackPanel elements that contain 15 images each.
To clarify:
I have a central StackPanel that has a vertical orientation. This StackPanel is located inside of a DataTemplate!.
<DataTemplate>
<Grid x:Name="ImageDisplayGrid" Height="861" Width="656">
<StackPanel x:Name="CentralImagePanel" HorizontalAlignment="Left" Height="841" Margin="10,10,0,0" VerticalAlignment="Top" Width="636"/>
</Grid>
</DataTemplate>
I have many instances of my wrapper class that contain up to 15 images each (as WritableBitmap objects.
I want to bind my central StackPanel to some method that will modify that StackPanel, iterating through my list of wrapper classes and adding child StackPanel controls to the central StackPanel for each instance of my wrapper class found.
For each instance of the (ImageSet1, ImageSet2, etc for example) wrapper class, the new StackPanel that will be added to the central StackPanel will be populated using the images contained in that wrapper class instance.
In my mind there isn't really anything to be 'returned' here, so I was hoping there was a way to just pass the control (the central StackPanel) to some method, let the method modify it, and then carry on after the central StackPanel is populated with its child `StackPanels'.
To clarify even more:
Think of NetFlix. You know how you can scroll vertically through each category and each category allows you to scroll horizontally? Thats what I am trying to emulate, only I want it to be dynamic and bound to my wrapper class that contains a list of Images to use.
My main obstacle right now is that the central StackPanel is located within a DataTemplate, so there isn't an easy way to access it during runtime. On top of that it would be nicer to use a binding anyway.
I have tried to use IValueConverter to turn my wrapper class into a list of StackPanel objects that the central StackPanel can use, but that didn't work. I've also searched for ways to bind a control to a method that has no return property without any luck as well.
Any help or examples would be greatly appreciated.
You are thinking about this wrong. Really, really, wrong. StackPanel is a layout control. You shouldn't ever be directly modifying its children or any other properties.
As you've noticed, there is no real way to do this task in the way you describe.
To display collections, use an ItemsControl. In your case, it would be something like:
<ItemsControl ItemsSource="{Binding Categories}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource={"Binding Videos"}>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- Whatever -->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Notice the inner template is another ItemsControl, this time with a horizontal StackPanel as the panel template.
I have a ListView and I bind to an ObservableCollection<Folder> and when I hover over a ListViewItem, there is a second selection thing appearing underneath (or ontop of) the item text which prevents me from being able to "activate" the selected item because it doesn't appear to be receiving my click.
As you can probably see, the structure is:
ListView > ItemTemplate > DataTemplate > ListViewItem. But I'm guessing I have that double-selection thing because there are basically 2 "item templates" (DataTemplate and ItemTemplate). But if I get rid of DataTemplate, it throws a runtime error. If I get rid of ItemTemplate, it throws an error. I can't win. How do I get rid of this thing?
Update:
This gives me the desired effect:
<StackPanel x:Name="folderContainer" HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="175" Background="Khaki" Margin="0, 18, 0, 0">
<ListView x:Name="folderList" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Folder}" BorderBrush="{x:Null}" BorderThickness="0">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="folderItem" Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
With the ListViewItem you where including a specialized wrapper primarily used the ListView to contain unknown item(s) presented by the binding of the ItemsSource when there is default template used. It helps to show that unknown item on the screen, its the purpose of the ListViewItem. For example if someone bound a list of strings, the strings have no xaml style on hover, hence there needs to be a container control to achieve all things graphical in those situations.
Why the two Shadows?
The actual ListViewItem is at its heart (or actually its property), a content control containing what I surmise you had was a textbox control. That is now two controls thanks to the DataTemplate you provided.
Hence you had a wrapper, with a content containing a texbox control. So there are two things which take up space, one is the ListViewItem and the other is the textbox. By hovering over each item, each's style kicked off to show the padding of the control as a selectable region in the Zorder fashion whereas both are seen.
Nothing more nothing less.
Since you knew what is to go into the content control, there was no need to use the ListViewItem wrapper, it was redundant, and you used the actual textbox; hence with only it's style to show the padding of the single control on hover.
I am trying to find a best or common practice for creating a table of buttons from a database list.
For my use I am creating more of a Point of Sale type screen. Where I want the categories to load as buttons on the entry screen. The buttons would have a simple task of showing a screen of more dynamically created buttons of the actual items. Those buttons would add the items to, lets call it, a ticket.
The solutions I found were few. I am also trying to code this so others can pick it up fairly quickly. I am extremely rusty and only code once in a while. So I try to follow common ways of doing it. I had some ideas but the code becomes hard to read, mostly because of me.
I saw the below link but was not sure if a ListBox was a good container for this.
Dynamic filling WrapPanel buttons from DB, setting the event handlers
I am sure a wrappenel is what I would have to use, but do I put it in a container or use it directly. Do I put it in Xaml or code it all, for issues like spacing between buttons? I think I am overthinking it and need to skip for a little bit.
Thank you,
It sounds like you want an ItemsControl, bound to your categories, with a WrapPanel as the ItemsPanel. The Button would go in the ItemTemplate.
<ItemsControl ItemsSource="{Binding CategoriesFromDatabase}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}"
Command="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.AddToTicketCommand}"
CommandParameter="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here I assumed that your view model has properties "CategoriesFromDatabase" (an IEnumerable that you populate from the database), and an ICommand "AddtoTicketCommand" which takes the category as a parameter.
Hi all i need to design a control that has a thumbnail views of picture.it can take list of pictures.i need it in wpf.is there any pre existed library of control?
if no how can i design i have no idea
Thanks
was looking something like http://www.codeproject.com/KB/graphics/crystal_image_grid_viewer.aspx?msg=3290254
If you have a list of pictures you can place a panel (StackPanel, WrapPanel, etc., depends on the behaviour you want) inside a ListBox. Set the panel to be the items host, and set the list of pictures as the ItemsSource. Something like this:
<ListBox x:Name="_listBox" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" IsItemsHost="true" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
and then in the code behind set _listBox.ItemsSource to your list of pictures.
(or you can have your list of pictures in an ObservableCollection and bind the ListBox to it)
EDIT: as for the thumbnails you can use something like:
BitmapImage Picture = new BitmapImage();
Picture.BeginInit();
Picture.UriSource = ... // your picture
Picture.DecodePixelWidth = ... //how big you want your pic
Picture.EndInit();
do you want to show all the images of the list at the same time? I believe you can use the grid and put a picture control in any cell of the grid, you can start with this approach, post your results and ask more specific questions once you have it at least partly done.