Tile view for ListView in WPf - wpf

How to simulate a tile view for a ListView in WPF?
I was trying the example shown here. But I can't get to the right solution... But I don't want to use that solution as I it's too much specific. So how will be the way to accomplilsh that?
EDIT: I'm trying this now and seems to work...
<ListBox ItemsSource="{Binding Path=ListObservableUsers, ElementName=AdminWindow}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Source="{Binding Path=Picture}"></Image>
<Label Content="{Binding Path=Dni}"></Label>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Where the ElementName=AdminWindow comes from <Window .... x:Name="AdminWindow"
And I created my own ObservableCollection<MyUser>
public class MyUser
{
public MyUser(int id, string dni, Bitmap picture)
{
Id = id;
Dni = dni;
Image img = new Image();
FPhiMultipleSources.FromBitmapImage(img, picture);
Picture = img.Source;
}
public int Id { get; set; }
public string Dni { get; set; }
public ImageSource Picture { get; set; }
}
...
public UCAdminMain()
public UCAdminMain()
{
ListObservableUsers = new ObservableCollection<MyUser>();
InitializeComponent();
uiCurrent = SynchronizationContext.Current;
// Create users to add with its image
....
ListObservableUsers.Add(...);
}
And now I'm trying to put them inside a wrap panel. With no luck right now... Any ideas?

<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
try to use a wrappanel

An ItemsControl with a WrapPanel as the ItemsContainer would probably be a good fit for what you are trying to do.

Related

ListBox bound to ObservableCollection not refreshing on view loaded

I have the following XAML containing a ListBox bound to an ObservableCollection
<ListBox
Margin="0,5"
Grid.Row="1"
Grid.ColumnSpan="3"
Visibility="{Binding ArePicturesAvailable, Converter={StaticResource BoolToVisConv}}"
SelectedItem="{Binding SelectedPicture}"
ItemsSource="{Binding Pictures, NotifyOnSourceUpdated=True}"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Image Margin="8"
Height="{Binding Size.Height}"
Width="{Binding Size.Width}"
Source="{Binding FullPath, Converter={StaticResource RelativeToFullConv}}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Since there is noticeable delay in populating the ListBox, I am attempting to defer this until the ListBox's containing view has loaded using Dispatcher.BeginInvoke as illustrated below:
public class PictureMarkerEditorViewModel
{
private PictureSelectorViewModel _pictureSelectorViewModel;
public string PhotoCollectionDirectory { get; set; }
protected ISymbolEditor GetEditorImpl(ISymbolInfo symbolInfo)
{
var picSymbolInfo = (PictureMarkerSymbolInfo)symbolInfo;
_pictureSelectorViewModel = new PictureSelectorViewModel(picSymbolInfo);
var editor = new PictureMarkerSymbolEditor(_pictureSelectorViewModel, picSymbolInfo);
editor.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
var photos = GetPhotoCollection();
_pictureSelectorViewModel.Pictures.AddRange(photos);
}));
//var photos = GetPhotoCollection();
//_pictureSelectorViewModel.Pictures.AddRange(photos);
return editor;
}
public IEnumerable<Picture> GetPhotoCollection()
{
if (string.IsNullOrEmpty(PhotoCollectionDirectory))
return null;
if (!Directory.Exists(PhotoCollectionDirectory))
throw new ArgumentException("Cannot show images from invalid directory " + PhotoCollectionDirectory + ".");
var files = Directory.GetFiles(PhotoCollectionDirectory, "*.png", SearchOption.AllDirectories);
return files.Select(f => new Picture(Path.GetFileName(f), f, ImageUtils.GetDimensions(f)));
}
}
where PictureSelectorViewModel.Pictures is simply an ObservableCollection of Picture:
public class PictureSelectorViewModel
{
private readonly ObservableCollection<Picture> _pictures= new ObservableCollection<Picture>();
public ObservableCollection<Picture> Pictures
{
get
{
return _pictures;
}
}
}
and Picture is a simple class containing Name and FullPath properties:
public class Picture
{
public string Name { get;set}
public string FullPath {get; set;}
public Size Size {get;set;}
}
I simply cannot get the list populated after it has loaded. If I populate the Pictures collection before the view is loaded (the commented part of the code, I see the images.
Any one know why?
TIA.

Binding data to ComboBox WPF

I am newbie to WPF, and needs help to bind data into the ComboBox. The xaml file contains the tag below.
<UserControl x:Class="SKAT.Postfordeler.Client.UI.View.ChooseInboxView"
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"
d:DesignHeight="42" d:DesignWidth="598">
<Grid>
<StackPanel Orientation="Horizontal">
<ComboBox Name="_currentInbox" Width="180" Margin="5" Height="22" DataContext="{Binding}" />
<Label Content="Et job kører allerede i denne indbakke (1500 ud af 1700 poster behandlet)" Name="_currentProcess" Margin="5" Height="25" />
</StackPanel>
</Grid>
//Inbox class , this class was implemented in seperate project
namespace SKAT.Postfordeler.Shared.DataTypes
{
[DataContract]
public class Inbox
{
[DataMember]
public String Id { get; set; }
[DataMember]
public String Folder { get; set; }
[DataMember]
public Rule Rules { get; set; }
}
}
//This code is located in the controller, the Activate method will fire when the MainWindow was executed
public void Activate()
{
var configuration = _configurationManager.GetConfiguration();// this method gets the xaml file settings
_chooseInboxView.FillInboxes(configuration.Inboxes); // Inboxes data binds to combobox
}
and in the View code behind, I created a method to bind the data which contains a type of list
public void FillInboxes(List<Inbox> inboxes)
{
DataContext = inboxes;
}
But it won't works,Any help please?
I assume your Inbox class consists of two properties (for simplicity), but there may be any number of them:
public class Inbox
{
public int ID { get; set; }
public string Text { get; set; }
}
You write a DataTemplate, for example:
<Grid.Resources>
<DataTemplate x:Key="InboxTemplate">
<WrapPanel>
<TextBlock Text="{Binding Path=ID}"/>
<TextBlock>:</TextBlock>
<TextBlock Text="{Binding Path=Text}"/>
</WrapPanel>
</DataTemplate>
</Grid.Resources>
Then correct your ComboBox declaration like:
<ComboBox Name="_currentInbox" Width="180" Margin="5" Height="22" ItemsSource="{Binding}" ItemTemplate="{StaticResource InboxTemplate}" />
Finally you set DataContext of your ComboBox to your List<Inbox>:
public void FillInboxes(List<Inbox> inboxes)
{
_currentInbox.DataContext = inboxes;
}
EDIT: As you've asked for a simpler solution, you can just override ToString() method of your Inbox class:
protected override string ToString()
{
return ID.ToString() + ":" + Text;
}
Instead of DataContext={Binding} you should have ItemsSource={Binding}.
The data context for any frameworkelement in the visual tree is by default {Binding}.
<ComboBox Name="_currentInbox"
SelectedItem="Hoved"
Width="180"
Margin="5"
Height="22"
DisplayMemberPath="Name"
ItemSource="{Binding}" />
Also for the combobox to display text of the items correctly I suppose you need DisplayMemberPath too. I assumed the property from Inbox class that you need to display is Name. Please replace with your relevant property name.
If your Inbox class is like,
public class Inbox
{
public int ID { get; set; }
public string Text { get; set; }
}
And if you do not want to change your xmal, the code behind method should be like this,
public void FillInboxes(List<Inbox> inboxes)
{
_currentInbox.DisplayMemberPath = "Text"; // To display the 'Text' property in the combobox dropdown
//_currentInbox.DisplayMemberPath = "ID"; // To display the 'ID' property in the combobox dropdown
_currentInbox.DataContext = inboxes;
}

WPF Listboxitem event trigger show popup

I am pretty much stuck on this and need some insight. When the user mouseover's a listboxitem I want to show some details regarding the item on which the mouse is currently over (hope I am making sense :( )
To demonstrate what I am wanting to achieve please see the sample code
public class Customer
{
public String FirstName { get; set; }
public Image CustomerPhoto { get; set; }
public Customer(String firstName, Image customerPhoto)
{
this.FirstName = firstName;
this.CustomerPhoto = customerPhoto;
}
}
public class Customers : ObservableCollection<Customer>
{
public Customers()
{
Image simpleImage = new Image();
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(#"c:\image.jpg",UriKind.RelativeOrAbsolute);
bi.EndInit();
simpleImage.Source = bi;
Add(new Customer("Customer", simpleImage));
}
}
XAML
<ListBox ItemsSource="{StaticResource customers}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now when the user hovers over the listbox item, I want to show the customerphoto in a popup.
Many Thanks
P.S: code was "cooked up" while writing this post, so is for demo only. There will be multiple items in the listbox, hovering over each item must show the photo associated with that object.
Why not just use the ToolTip? In WPF, ToolTips don't have to be text-only
<TextBlock.ToolTip>
<ToolTip>
<Image Source="{Binding CustomerPhoto}" />
</ToolTip>
</TextBlock.ToolTip>

Get name of selected listbox item (WPF C#)?

all. I have an app that scans a picture folder and displays the images along with their names in a listbox. Each image and image name (displayed in a textblock next to the image) is stored in a horizontal stackpanel inside the listbox.
I've been trying all afternoon to find a way of displaying the image name in a textbox when the user selects it in the listbox. Sounds very simple, and I'm sure it is, but I can't seem to get it to work.
Can anyone point me in the right direction as to the best way of doing this? Thanks.
Here is my xaml if it helps:
<Grid>
<ListBox ItemsSource="{Binding AllImages}" Margin="0,0,262,0" Name="listBox1" MouseLeftButtonDown="listBox1_MouseLeftButtonDown">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" Width="50" Height="50" Margin="6"/>
<TextBlock Text="{Binding Name}" Margin="6" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Height="23" HorizontalAlignment="Left" Margin="265,148,0,0" Name="textBox1" VerticalAlignment="Top" Width="198" />
</Grid>
And my code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public class MyImage
{
private ImageSource _image;
private string _name;
public MyImage(ImageSource image, string name)
{
_image = image;
_name = name;
}
public override string ToString()
{
return _name;
}
public ImageSource Image
{
get { return _image; }
}
public string Name
{
get { return _name; }
}
}
public List<MyImage> AllImages
{
get
{
List<MyImage> result = new List<MyImage>();
string filePath = #"D:\Projects\Visual Studio 2010\WpfApplication5\WpfApplication5\bin\Debug\ImageFolder";
string[] files = Directory.GetFiles(filePath);
foreach (string filename in files)
{
try
{
result.Add(
new MyImage(
new BitmapImage(
new Uri(filename)),
System.IO.Path.GetFileNameWithoutExtension(filename)));
}
catch { }
}
return result;
}
}
}
Take a look at this question.
How do I bind a Listview SelectedItem to a Textbox using the TwoWay mode?
In your case use
<TextBox Height="23"
HorizontalAlignment="Left"
Margin="265,148,0,0"
Name="textBox1"
VerticalAlignment="Top" Width="198"
Text="{Binding SelectedItem.Name, ElementName=listBox1}"/>
To retrieve the selected image from code, you have at least 3 options (I assume your images are represented by a class ImageItem)
Set IsSynchronizedWithCurrentItem to true on your ListBox, and use the following code to retrieve the selected item:
ICollectionView view = CollectionViewSource(AllImages);
ImageItem selectedImage = (ImageItem)view.CurrentItem;
Bind the SelectedItem of the ListBox to a property in your DataContext:
<ListBox .... SelectedItem="{Binding SelectedImage}">
Access the SelectedItem property directly from code-behind:
ImageItem selectedImage = (ImageItem)listBox1.SelectedItem;
Of course, if you just want to show the name in a TextBlock, you can use Russell Troywest's solution

WPF Listbox Images from a database

(How long have we been using OpenIDs? I don't seem to have one connected to any provider and no FAQ on the planet seems to tell you what to do when you lose your OpenID. I've had to create a new account. Argh!)
I'm trying to fill a (carousel) listbox from a database, but I can't get the images to display. Every single example on the net assumes you have two or three jpegs in a folder instead of in memory :(
My item class is:
public class PicCollection : ObservableCollection<CarouselItem>
{
public PicCollection()
{
}
}
public class CarouselItem
{
public int ItemID { get; set; }
public string ItemName { get; set; }
public string ItemDesc { get; set; }
public Image ItemImage { get; set; }
public CarouselItem(int NewItemID, string NewItemName, string NewItemDesc, Image newItemImage)
{
this.ItemID = NewItemID;
this.ItemName = NewItemName;
this.ItemDesc = NewItemDesc;
this.ItemImage = newItemImage;
}
}
I fill a PicCollection successfully from the db(using a byte array for the image), and try to display the name and image with
<DataTemplate x:Key="TestDataTemplate2" >
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="CarName"
Text="{Binding ItemName}"
Padding="15,15"
Foreground="Yellow" />
<Image Source="{Binding Source=ItemImage}"
Stretch="Fill" />
</StackPanel>
</DataTemplate>
Listbox is simply:
<ListBox Name="lstTest" ItemsSource="{StaticResource TestDataSource}"
ItemTemplate="{StaticResource TestDataTemplate2}"></ListBox>
ItemName displays ok, ItemImage does not. I've tried {Binding ItemImage} as well. Most examples use {Binding Path=ItemImage} but that's where the ItemImage would be a string containing the path, not the actual image itself.
I'm pulling my hair out. Nothing I do makes the images appear. If I create an image control and manually assign the contents of an ItemImage, however, it displays fine. What am I doing wrong?
Your ItemImage property is an Image (control). Make it an ImageSource, such as a System.Windows.Media.Imaging.BitmapImage. Then you can bind <Image Source="{Binding ItemImage}" />.
Since your "ItemImage" property is already an image, you might be able to get away with just using a ContentControl to display the image directly:
<ContentControl Content="{Binding Image}" />

Resources