Reputation: 8315
I was exploring DataTemplate
and found Styling and Templating on MSDN. It says -
"In this sample application, there is a ListBox control that is bound to a list of photos:
<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
Background="Silver" Width="600" Margin="10" SelectedIndex="0"/>
This ListBox currently looks like the following:"
//...some stuff about DataTemplate
...//
In our sample application, each custom Photo
object has a Source
property of type string that specifies the file path of the image. Currently, the photo objects appear as file paths."
"For the photos to appear as images, you create a DataTemplate as a resource:"
<Window.Resources>
...
<!--DataTemplate to display Photos as images
instead of text strings of Paths-->
<DataTemplate DataType="{x:Type local:Photo}">
<Border Margin="3">
<Image Source="{Binding Source}"/>
</Border>
</DataTemplate>
...
</Window.Resources>
OK, fair enough, so I declared the Photo class -
public class Photo
{
public string Source { get; set; }
}
My XAML sense is not very good (it's bad actually). What I don't get here is the way ItemsSource of the ListBox is set. As far as my XAML goes, "MyPhotos" here have to be an x:Key
to an IEnumerable object of Photo type, something like -
<Window.Resources>
...
<local:PhotoList x:Key="MyPhotos"/>
...
</Window.Resources>
But I don't have any idea how the PhotoList class should look like in this case. So, what the Resource would actually look like that cause the ListBox to be populated with the Source
strings of the photos?
FYI : Implementing things in my own way, my DataTemplate
exploration got successful, and though this thing here was not my primary concern, I just want to know what I don't know. Can anyone shed some light?
EDIT in response to the Answer provided by H.B.:
The point of the question is to get the result, as shown in the image, before applying the DataTemplate and to get an idea of the Resource that make that happen.
If I make the PhotoList
itself an IEnumerable, like -
public class PhotoList : List<Photo>
{
//some property to hold the collection of Photo objects??
}
and instantiate it within the Resource, then to what the ItemsSource
actually gets bound? How it's gonna work? Sorry I didn't understand. I hope you'll elaborate a bit more on this.
So, I went for the DataSourceProvider
option. But since the Data
property has no setter, I tried the following -
public class Photo
{
public string Source { get; set; }
}
public class PhotoList : DataSourceProvider
{
private List<Photo> _photos;
public PhotoList()
{
_photos = new List<Photo>
{
new Photo{ Source = @"D:\AppImage\1.jpg"},
new Photo{ Source = @"D:\AppImage\2.jpg"},
new Photo{ Source = @"D:\AppImage\3.jpg"},
new Photo{ Source = @"D:\AppImage\4.jpg"},
new Photo{ Source = @"D:\AppImage\5.jpg"},
};
((List<Photo>)this.Data).AddRange(_photos);
}
}
And definitely I'm doing something wrong. Because, now i get the Cannot create an instance of "PhotoList" error message while instantiating PhotoList
within the Resource -
<Window.Resources>
<local:PhotoList x:Key="MyPhotos"/>
</Window.Resources>
Please help me out here.
Upvotes: 0
Views: 2116
Reputation: 185225
The PhotoList
itself either has to be an IEnumerable
of Photo
objects, or it needs to provide one, this can be done by inheriting from DataSourceProvider
and exposing the list that way.
Edit:
Obviously if you just inherit from List<T>
nothing will display unless you add items, when i said it should be an IEnumerable
i meant an immediate implementation that actually enumerates strings right away. If you just want to create a list in XAML you may as well use x:Array
.
Also here would be an example of using the DataSourceProvider
:
public class PhotoList : DataSourceProvider
{
protected override void BeginQuery()
{
var files = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures))
.Where(f => Path.GetExtension(f) == ".png")
OnQueryFinished(files);
}
}
This will populate your list with the paths of PNG-files in the personal "Pictures" folder.
Also you will not get the DataTemplate
-less appearance of the example if you use a class like Photo
unless you override ToString
to return the source URL because by default if there is no DataTemplate
it will just display the full name of the class.
In any case you need Photo
objects in your collection for the DataTemplate
to apply properly. Also you usually do not have collections directly in XAML but some data object which is the DataContext
of the Window
/UserControl
.
Upvotes: 1
Reputation: 4680
<Window.Resources>
<ph:PhotoList x:Key="MyPhotos" Path="D:\Visual Studio Projects\WPF APPLICATIONS\ImageViewer\ImageViewer\Images">
</ph:PhotoList>
</Window.Resources>
Upvotes: 0