I am trying to get data from two array lists into a window. The first array list contains images and the second array list contains names of movies.
The layout will show movie posters along with the names of the relevant movie underneath the poster. The code I am currently using doesn't seem to be working properly as I only get images showing in the window but no text.
This the current XAML code I have:
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<WrapPanel Orientation="Vertical">
<Image Width="200" Height="300" Stretch="Fill" Source="{Binding}"/>
<TextBlock Text="{Binding movie_names}" HorizontalAlignment="Center"/>
</WrapPanel>
</DataTemplate>
</Window.Resources>
<Grid x:Name="movie_grid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<ListView Grid.Row="1"
Name="MovieListView"
ItemTemplate="{StaticResource ItemTemplate}"
ItemsSource="{Binding Path = movie_posters_list}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
<TextBlock Name="SampleTextBlock"
Text="{Binding Path=movie_names}"
DataContext="{StaticResource ItemTemplate}" />
</Grid>
</Window>
And here is the C# code behind:
public partial class MoviePanel : Window {
public MoviePanel() {
InitializeComponent();
}
List<ImageSource> movie_posters_list = new List<ImageSource>();
List<String> movie_names = new List<String>();
String regex_pattern = #"\\([\w ]+).(?:jpg|png)$";
public void LoadImages() {
//Image current_image;
String movie_poster_path = #"C:\Users\Vax\Desktop\movie_posters";
List<String> filenames = new List<String>(System.IO.Directory.EnumerateFiles(movie_poster_path, "*.jpg"));
foreach (String filename in filenames) {
this.movie_posters_list.Add(new BitmapImage(new Uri(filename)));
Match regex_match = Regex.Match(filename.Trim(), regex_pattern);
String matched_movie_name = regex_match.Groups[1].Value;
this.movie_names.Add(matched_movie_name);
}
MovieListView.ItemsSource = movie_posters_list;
MovieListView.DataContext = movie_names;
}
}
I think the issue stems from binding the data but I'm not sure what I've done wrong.
Create a model class and wrap your Movie Name and Image into it.
public class MovieDetail
{
public ImageSource Image { get; set; }
public string Name { get; set; }
}
When calling LoadImages, add instances of this model into ListView. And modify the datatemplate to bind the Name and Image.
List<MovieDetail> movies = new List<MovieDetail>();
foreach (String filename in filenames)
{
Match regex_match = Regex.Match(filename.Trim(), regex_pattern);
String matched_movie_name = regex_match.Groups[1].Value;
movies.Add(new MovieDetail { Image = new BitmapImage(new Uri(filename)), Name = matched_movie_name });
}
MovieListView.ItemsSource = movies;
The DataTemplate,
<DataTemplate x:Key="ItemTemplate">
<WrapPanel Orientation="Vertical">
<Image Width="200"
Height="300"
Stretch="Fill"
Source="{Binding Image}" />
<TextBlock Text="{Binding Name}"
HorizontalAlignment="Center" />
</WrapPanel>
</DataTemplate>
Related
I want to play MediaElement briefly and then stop it when add listbox items.
It looks like Video Thumbnail. I created a list box dynamically, can I play it back and stop it?
Main.xaml
<ListBox Grid.Row="0" x:Name="listBox" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" AllowDrop="True" Drop="ListBox_Drop" DragEnter="ListBox_DragEnter" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Disabled" MouseMove="ListBox_MouseMove">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<MediaElement Margin="3" x:Name="{Binding vName}" Source="{Binding Path}" Height="64" Stretch="Uniform" IsMuted="True"/>
<TextBlock Margin="3" Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Main.xaml.cs
private void Add_Item(string file)
{
extension = Path.GetExtension(file);
file_name = Path.GetFileName(file);
if (extension.Equals(".mp4") || extension.Equals(".mwv") || extension.Equals(".avi"))
{
list.Add(new VideoListing()
{
Name = file_name,
Path = file,
vName = file_name,
});
}
listBox.ItemsSource = list;
listBox.Items.Refresh();
}
VideoListing.cs
class VideoListing
{
public string Name { get; set; }
public string Path { get; set; }
public string vName { get; set; }
}
OK, I think similar questions have already been asked, but I can't get this to work. I have a View with an ItemsControl like this:
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Content="Model Health Report:" Margin="10,10,10,0" Height="26" VerticalAlignment="Top" FontWeight="Bold"/>
<ItemsControl Grid.Row="1"
ItemsSource="{Binding HealthReports, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type hr:HealthReportSummaryControl}"/>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
That has a view model behind it like this:
public class CommunicatorViewModel : ViewModelBase
{
public ObservableCollection<HealthReportSummaryViewModel> HealthReports { get; set; }
public CommunicatorModel Model { get; set; }
public CommunicatorViewModel(HealthReportData data)
{
Model = new CommunicatorModel();
HealthReports = new ObservableCollection<HealthReportSummaryViewModel>
{
new HealthReportSummaryViewModel {Title = "View1", Description = "Some desc."},
new HealthReportSummaryViewModel {Title = "View2", Description = "Some desc."}
};
}
}
As you can see I am binding it to an ObservableCollection of HealthReportSummaryViewModel objects. These are populated in the constructor. I checked the objects at runtime, they are correct.
The actual control looks like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="2"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Ellipse Grid.Column="0"
Fill="{Binding FillColor}"
Margin="2"/>
<Rectangle Grid.Column="1"
Fill="DarkGray"
Margin="0,2"/>
<Label Content="{Binding Title}"
Grid.Column="2"
Margin="5,0,10,0"
VerticalAlignment="Top"/>
<TextBlock Grid.Column="2"
Margin="5,10,10,0"
TextWrapping="Wrap"
Text="{Binding Description}"/>
</Grid>
With a view model:
public class HealthReportSummaryViewModel : ViewModelBase
{
private System.Windows.Media.Color _fillColor;
public System.Windows.Media.Color FillColor {
get { return _fillColor; }
set { _fillColor = value; RaisePropertyChanged(() => FillColor); }
}
private string _title;
public string Title
{
get { return _title; }
set { _title = value; RaisePropertyChanged(() => Title); }
}
private string _description;
public string Description
{
get { return _description; }
set { _description = value; RaisePropertyChanged(() => Description); }
}
}
I am getting no exceptions, but my window has only empty items. There is a rectangle in the user control that is not dependent on data binding so perhaps this is an issue with the size of the content? I can't figure this out. It's all blank. Do I need to somehow set the size for each ItemsControl item, or will they just adjust to size of the grid they are placed in? What am i missing here? All help will be appreciated.
Your DataTemplate definition is wrong:
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type hr:HealthReportSummaryControl}"/>
</ItemsControl.ItemTemplate>
This defines an empty data template for the items of the HealthReportSummaryControl type.
Instead, you should define it like that:
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type hr:HealthReportSummaryViewModel}">
<hr:HealthReportSummaryControl/>
</DataTemplate>
</ItemsControl.ItemTemplate>
This defines a template for the HealthReportSummaryViewModel items.
I want to draw listbox items on a Canvas, place them somewhere, and then move them around, finding inspiration in the following very good example Brewer Floating Content. However I don't want to duplicate this specific example from the blog.
Hence I attempt to draw items on listbox with a Canvas, but fail again, though in WPF this works easily.
The XAML code is:
<UserControl.Resources>
<DataTemplate x:Key="ThingTemplate" x:DataType="local:Thing">
<Border Width="150" BorderBrush="#FF9B3333" BorderThickness="2"
ManipulationMode="TranslateX, TranslateY, TranslateInertia"
ManipulationDelta="Border_ManipulationDelta">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Border Background="#FF9B3333" Grid.Row="1">
<TextBlock Text="{Binding Comment}" HorizontalAlignment="Center"
VerticalAlignment="Center" TextWrapping="WrapWholeWords" Foreground="Black" Padding="4" />
</Border>
</Grid>
</Border>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ListBox x:Name="ThingCanvas" Grid.Row="1" ItemTemplate="{StaticResource ThingTemplate}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
and the source code-behind:
public sealed partial class UserControl1 : UserControl
{
public UserControl1()
{
this.InitializeComponent();
for (var i = 0; i < 4; i++)
{
var newThing = new Thing() { Comment = "Item" + i.ToString() };
ThingCanvas.Items.Add(newThing);
}
}
private void Border_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var left = Canvas.GetLeft(this) + e.Delta.Translation.X;
var top = Canvas.GetTop(this) + e.Delta.Translation.Y;
Canvas.SetLeft(this, left);
Canvas.SetTop(this, top);
}
}
public class Thing
{
public string ImagePath { get; set; }
public string Comment { get; set; }
}
Strange is that the Canvas cannot access to IsItemsHost property, which is set in WPF.
Also hindering is that style setters cannot be databound in UWP, so that Canvas.Left and Canvas.Top cannot be bound.
Thank you for helping me advance on this topic.
RudiAcitivity
I'm trying to populate a Combo with images. It is defined as:
<ComboBox SelectedItem="{Binding SelectedLangComboItem}"
ItemsSource="{Binding Languages}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" />
<TextBlock Text="{Binding Label}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Where the items are the LanguageItem classes:
public class LanguageItem
{
public System.Drawing.Bitmap Image { get; set; }
public string Label { get; set; }
public string Culture { get; set; }
public LanguageItem(System.Drawing.Bitmap image, string label, string culture)
{
Image = image;
Label = label;
Culture = culture;
}
}
Now, in my ViewModel c'tor I do:
_Languages = new ObservableCollection<LanguageItem>();
System.Reflection.Assembly app = System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Stream file;
file = app.GetManifestResourceStream("MyNamespace.Images.FLAG1.gif");
_Languages.Add(new LanguageItem(new Bitmap(file), "ITALIAN", "it-IT"));
file = app.GetManifestResourceStream("MyNamespace.Images.FLAG2.gif");
_Languages.Add(new LanguageItem(new Bitmap(file), "ENGLISH", "en-EN"));
this.SelectedLangItem = _Languages[0];
The images are embedded resources. Here I have two problems:
The images are not displayed;
The Item is not selected, the SelectedLangItem is:
public LanguageItem SelectedLangItem
{
get { return _SelectedLangItem; }
set
{
if (_SelectedLangItem == value)
return;
_SelectedLangItem = value;
this.RaisePropertyChanged("SelectedLangItem");
}
}
Use
new BitmapImage(new Uri("MyNamespace.Images.FLAG1.gif", UriKind.Relative));
as it have to implement ImageSource
And regarding not selected: Property name is "SelectedLangItem" while in xaml SelectedLangComboItem if you did not mistype.
CODE:
this.RaisePropertyChanged("SelectedLangItem");
XAML:
<ComboBox SelectedItem="{Binding SelectedLangComboItem}"
Your problem is that you are trying to bind an Image to the Image.Source property, which is of type ImageSource.
The easiest solution is to add your actual image files into a folder and change the Image property in your class to a string that holds the file path to the image in this format:
/ApplicationName;component/ImageFolderName/ImageName.png
Then you can correctly bind this string (which the Framework will convert into an ImageSource object) to the Image.Source property in your DataTemplate.
Try below xaml code and bind image list into combobox...
<Window.Resources>
<DataTemplate x:Key="cmbTemplate">
<WrapPanel Margin="0 5 0 5" Height="80">
<Image Width="65" Height="65" Stretch="Fill" Source="{Binding Photo}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,15,0"/>
<Label Content="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20"/>
</WrapPanel>
</DataTemplate>
</Window.Resources>
<StackPanel HorizontalAlignment="Center">
<Label Content="Dropdown list with Image" HorizontalAlignment="Center" FontSize="30" Margin="20"/>
<ComboBox x:Name="lstwithimg" HorizontalAlignment="Center" VerticalAlignment="Top" ItemTemplate="{StaticResource cmbTemplate}" Height="80" Width="400"/>
</StackPanel>
Check below... for more understanding of live example...
http://www.codescratcher.com/wpf/wpf-combobox-with-image/
I have two DataTemplates defined within my XAML, each used for a seperate ItemsControl panel.
The main ItemsControl lists Foo objects stored within an ObservableCollection object.
The Foo object itself has its own set of items stored within as an ObservableCollection object.
I tried to define the XAML in a way that allows for each of the ObservableCollection Foo items to be displayed with its name in a header (The first ItemsControl). From this the list within each Foo item itself should be displayed horizontally (Using the second ItemsControl) with a related field directly below. If enough items are present then they should wrap to the next line where necessary.
This is how the UI currently stands:
This is how I wish the UI to actually appear:
My Markup (Button controls are for another aspect of the UI) :
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<ItemsControl x:Name="ContentList" ItemTemplate="{StaticResource GameTemplate}" Grid.Column="0" />
</ScrollViewer>
<StackPanel Grid.Column="1" Background="DarkGray">
<Button Click="OnLoad">_Load</Button>
<Button Click="OnSave">_Save</Button>
<Button Click="OnAdd">_Add</Button>
<Button Click="OnDelete">_Delete</Button>
</StackPanel>
</Grid>
DataTemplate for listing Foo items:
<DataTemplate x:Key="GameTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Content="{Binding Name}" Grid.Row="0" Background="Gray" FontSize="16" />
<ItemsControl x:Name="imageContent"
ItemsSource="{Binding FileList}"
ItemTemplate="{StaticResource GameImagesTemplate}"
Grid.Row="1" />
</Grid>
</DataTemplate>
DataTemplate for listing items within each Foo item:
<DataTemplate x:Key="GameImagesTemplate">
<WrapPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical" >
<Image Source="{Binding FileInfo.FullName}"
Margin="8,8,8,8"
Height="70"
Width="70" />
<Label Content="{Binding Name}" />
</StackPanel>
</WrapPanel>
</DataTemplate>
I'm fairly new to WPF so I have a feeling it's an issue caused by how I am using the controls.
What WPF changes would I need to make in order to generate the UI I would like?
I think its because you are adding each image item to a new WrapPanel in GameImagesTemplate , you should just have to set the ItemsControl ItemsPanelTemplate to WrapPanel in the GameTemplate
Example:
Xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="252.351" Width="403.213" Name="UI" >
<Window.Resources>
<DataTemplate x:Key="GameImagesTemplate" >
<StackPanel>
<Image Source="{Binding FileInfo.FullName}" Margin="8,8,8,8" Height="70" Width="70" />
<Label Content="{Binding Name}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="GameTemplate">
<StackPanel>
<Label Content="{Binding Name}" Grid.Row="0" Background="Gray" FontSize="16" />
<ItemsControl x:Name="imageContent" ItemsSource="{Binding FileList}" ItemTemplate="{StaticResource GameImagesTemplate}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<ItemsControl ItemsSource="{Binding ElementName=UI, Path=FileList}" Grid.Column="0" ItemTemplate="{StaticResource GameTemplate}" />
</ScrollViewer>
</Grid>
</Window>
Code:
public partial class MainWindow : Window
{
private ObservableCollection<Foo> _fileList = new ObservableCollection<Foo>();
public MainWindow()
{
InitializeComponent();
foreach (var item in Directory.GetDirectories(#"C:\StackOverflow"))
{
FileList.Add(new Foo
{
Name = item,
FileList = new ObservableCollection<Bar>(Directory.GetFiles(item).Select(x => new Bar { FileInfo = new FileInfo(x) }))
});
}
}
public ObservableCollection<Foo> FileList
{
get { return _fileList; }
set { _fileList = value; }
}
}
public class Foo
{
public string Name { get; set; }
public ObservableCollection<Bar> FileList { get; set; }
}
public class Bar
{
public FileInfo FileInfo { get; set; }
}
Result