Here's my problem, I want to have a few ListViews with their ItemsSource attached with binding to SelectedItem of other ListViews.
Here's a picture to show you the interface to give you an overlook :
So I have a "Tours" ListView who's ItemSource is bonded with a ObservableCollection property.
Now I want the "Parties" ListView to be bond with the SelectedItem of the "Tours" ListView.
Afterwards, I want the "Équipes" ListView to be bound with the SelectedItem of the "Parties" ListView.
And so on...
Right now, it is working, but the program crash :
Select a "Tour" from "Tours"
Select a "Partie" from "Parties"
Select a "Équipe" from "Équipes"
Select a "Different "Tour" from "Tours"
Crash
I supposed it was when I change "Tour", the "Équipe" point toward something inexistant.
This is the XAML of the ListViews and the content (the content isn't bond right now) :
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel>
<Label Style="{StaticResource menu}" Content="Tours" />
<ListView Name="lvTours" ItemsSource="{Binding Tours}" SelectionChanged="lvTours_SelectionChanged">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Nom}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
<Label Style="{StaticResource menu}" Content="Parties" />
<ListView Name="lvParties" DataContext="{Binding RelativeSource={RelativeSource Self}}" SelectionChanged="lvParties_SelectionChanged" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Nom}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
<Label Style="{StaticResource menu}" Content="Équipes" />
<ListView Name="lvEquipes" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Nom}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
</StackPanel>
<Label Content="Here's the content..." Grid.Column="1" Margin="30" />
</Grid>
And here's the cs :
using Lama.Logic.Model.Test;
using System.Windows.Controls;
namespace Lama.UI.UC.TournoiControls.StatistiquesControls
{
/// <summary>
/// Interaction logic for Statistiques.xaml
/// </summary>
public partial class StatistiquesUC : UserControl
{
public Tour SelectedTour { get; set; }
public Partie SelectedPartie { get; set; }
public StatistiquesUC()
{
InitializeComponent();
}
private void lvTours_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
lvParties.ItemsSource = ((Tour)lvTours.SelectedItem).Parties;
}
private void lvParties_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
lvEquipes.ItemsSource = ((Partie)lvParties.SelectedItem).Equipes;
}
}
}
So :
"Tours" is a property of ObservableCollection
each "Tour" has a property "Parties" of ObservableCollection
each "Partie" has a property "Equipes" of ObservableCollection
and so on...
Thanks and sorry for my english!
Since you dont want a ViewModel, this is an other approche :
In your xaml does not need to SelectionChanged, just bind itemSource of Lisview Equipe & Partie the parent list view like this :
<Grid DataContext="{Binding YourViewModel}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel>
<Label Style="{StaticResource menu}" Content="Tours" />
<ListView Name="lvTours" ItemsSource="{Binding Tours}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Nom}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
<Label Style="{StaticResource menu}" Content="Parties" />
<ListView Name="lvParties" ItemsSource="{Binding ElementName=lvTours, Path=SelectedItem.Parties}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Nom}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
<Label Style="{StaticResource menu}" Content="Équipes" />
<ListView Name="lvEquipes" ItemsSource="{Binding ElementName=lvParties, Path=SelectedItem.Equipes}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Nom}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
</StackPanel>
<Label Content="Here's the content..." Grid.Column="1" Margin="30" />
</Grid>
Hope it helps
Related
I'm developing my frist app on xamarin-forms, using XamarinForms v4.2, Prism.Dryloc v7.2 and Refit.
I have 3 collectionview on my MenuPage
Food
Drinks
Cart
A web service fills the first two and they work great, I need to select one of each one and I'm trying to binding the selected items to the Cart collection, I'm debugging to understand how it works but at the moment of selection this appear on my Debug Console:
"[0:] Binding: KioscoColab.Models.Menu can not be converted to type 'System.Collections.ObjectModel.ObservableCollection'1[KioscoColab.Models.Menu]
Here is my code:
ViewModel
...
ObservableCollection<Menu> _food;
ObservableCollection<Menu> _drinks;
ObservableCollection<Menu> _cart;
public ObservableCollection<Menu> Food
{
get => _food;
set => SetProperty(ref _food, value);
}
public ObservableCollection<Menu> Drinks
{
get => _drinks;
set => SetProperty(ref _drinks, value);
}
public ObservableCollection<Menu> Cart
{
get => _cart;
set => SetProperty(ref _cart, value);
}
...
public async Task LoadMenu()
{
//Here is my logic for the web service
...
Food = new ObservableCollection<Menu>(food.Content);
Drinks = new ObservableCollection<Menu>(drinks.Content);
Cart = new ObservableCollection<Menu>();
}
...
XamlPage
<!-- CollectionView Food-->
<CollectionView
Grid.Row="1"
Grid.Column="0"
Margin="5"
ItemsSource="{Binding Food}"
SelectedItem="{Binding Cart, Mode=TwoWay}"
SelectionMode="Single"
VerticalScrollBarVisibility="Always">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="0"
FontSize="Medium"
Text="{Binding Description}"
VerticalOptions="Center" />
<Label
Grid.Column="1"
FontSize="Medium"
HorizontalTextAlignment="End"
Text="{Binding Price, StringFormat='{0:C}'}"
VerticalOptions="Center" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<!-- CollectionView Cart -->
<CollectionView
Grid.Row="1"
Grid.Column="1"
Margin="5"
ItemsSource="{Binding Cart}"
VerticalScrollBarVisibility="Always">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="2" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="0"
FontSize="18"
Text="{Binding Description}"
VerticalOptions="Center" />
<Label
Grid.Column="1"
FontSize="18"
Text="{Binding Price}"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
How can I make the cast? Or what should I do?
I have a list view with following code:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="allToDoItemsListBox"
ItemsSource="{Binding AllToDoItems,Mode=OneWay}"
Margin="12,0,12,0"
Width="440"
ItemTemplate="{StaticResource ToDoListBoxItemTemplate}" />
</Grid>
The datatemplate is as follows :
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="ToDoListBoxItemTemplate">
<Grid HorizontalAlignment="Stretch" Width="420">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<CheckBox
IsChecked="{Binding IsComplete, Mode=TwoWay}"
Grid.Column="0" VerticalAlignment="Top"/>
<TextBlock
Text="{Binding ItemName}"
FontSize="{StaticResource PhoneFontSizeLarge}"
Foreground="Gray"
Grid.Column="1" Grid.ColumnSpan="2"
VerticalAlignment="Top" Margin="-36, 12, 0, 0"/>
<Button
Grid.Column="3"
x:Name="deleteTaskButton"
BorderThickness="0"
Margin="0, -18, 0, 0"
Command="{Binding Path=DeleteCommand}" CommandParameter="{Binding}"/>
<Image
Source="/Images/appbar.delete.rest.png"
Height="75"
Width="75"/>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
I tried to bind the Button Command "DeleteCommand" to a ICommand in ViewModel but it failed what should i do?
The Code in ViewModel is :
public ICommand DeleteCommand { get; private set; }
In the ViewModel Construct :
DeleteCommand = new RelayCommand<object>(Delete);
And The delete method :
private void Delete(object obj)
{
ToDoItem newToDoItem = obj as ToDoItem;
DeleteToDoItem(newToDoItem);
}
I need to pass the item to DeleteToDoItem() method as parameter when the corresponding delete button of each item in the list is pressed but the command does not fire here what should i do?
In your ViewModel you want to pass a ToDoItem to your Delete command.
DeleteCommand = new RelayCommand<ToDoItem>(DeleteToDoItem);
And your DataTemplate's DataContext is different from the ListView's.
<Button Command="{Binding ElementName=allToDoItemsListBox,
Path=DataContext.DeleteCommand}"
CommandParameter="{Binding}" />
That should do it.
Here is my problem i need to solve.
My data content is in DemoList class:
NOTICE: DemoHeader object contains a ObservableCollection of DemoItem objects, and DemoList object contains ObservableCollection of DemoHeader objects
public enum Type
{
article,
product,
material
}
public class DemoHeader
{
private ObservableCollection<DemoItem> _items;
public ObservableCollection<DemoItem> Items
{
get { return _items; }
set { _items = value; }
}
public DemoHeader(string document)
{
this._salesOrder = document;
_items = new ObservableCollection<DemoItem>();
}
private string _salesOrder;
public string SalesOrder
{
get { return _salesOrder; }
set { _salesOrder = value; }
}
}
public class DemoItem
{
public DemoItem(string name, Type type)
{
this._name = name;
this._type = type;
}
private Type _type;
public Type Type
{
get { return _type; }
set { _type = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
public class DemoList : ObservableCollection<DemoHeader>//, ICollectionView
{
public DemoList()
{
DemoHeader dd = new DemoHeader("Doc-1");
dd.Items.Add(new DemoItem("T-1", Type.article));
dd.Items.Add(new DemoItem("M-1", Type.material));
DemoHeader dd2 = new DemoHeader("Doc-2");
dd2.Items.Add(new DemoItem("P-1", Type.product));
dd2.Items.Add(new DemoItem("P-2", Type.product));
this.Add(dd);
this.Add(dd2);
}
}
XAML:
NOTICE: I have 4 CollectionViewSource for each ListBox.
<Window x:Class="WuZet.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:WuZet"
Title="WuZet" WindowStartupLocation="CenterScreen" ResizeMode="CanResize" Loaded="window_loaded" Background="#ECE9D8" WindowStyle="ToolWindow" Icon="/WuZet;component/Images/ksi_ikona.ico" Topmost="True" WindowState="Maximized" SizeToContent="WidthAndHeight">
<Window.Resources>
<CollectionViewSource x:Key="list" Source="{Binding}"></CollectionViewSource>
<CollectionViewSource x:Key="wares" Source="{Binding Source={StaticResource list}, Path=Items}" Filter="wareFilter"></CollectionViewSource>
<CollectionViewSource x:Key="materials" Source="{Binding Source={StaticResource list}, Path=Items}" Filter="materialFilter"></CollectionViewSource>
<CollectionViewSource x:Key="products" Source="{Binding Source={StaticResource list}, Path=Items}" Filter="productFilter"></CollectionViewSource>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="2" Margin="5,5,5,5">
<TextBox/>
<Button Content="ok" Margin="0,5,0,0" HorizontalAlignment="Stretch" Height="30" Width="150" Click="Button_Click"/>
</StackPanel>
<StackPanel Grid.RowSpan="2" Grid.Column="2">
<ListBox Name="orders" IsEnabled="{Binding ElementName=check, Path=IsChecked}" Margin="85,5,85,5" Height="70" ItemsSource="{Binding Source={StaticResource list}}" DisplayMemberPath="SalesOrder"/>
<CheckBox Name="check" HorizontalAlignment="Center" Content="Wybierz zamówienie" IsChecked="False"/>
</StackPanel>
<GroupBox Header="Wares" Grid.Row="2" Grid.Column="0">
<ListBox Name="lbWares" ItemsSource="{Binding Source={StaticResource wares}}" >
<ListBox.ItemTemplate>
<DataTemplate>
<!--<StackPanel Orientation="Horizontal">-->
<TextBlock Text="{Binding Path=Name}"></TextBlock>
<!--<TextBlock Text="{Binding ZaE_TwrKod}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_Ilosc}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_TwrNazwa}" />-->
<!--</StackPanel>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
<GroupBox Header="Materials" Grid.Row="2" Grid.Column="1">
<ListBox Name="lbMaterials" ItemsSource="{Binding Source={StaticResource materials}}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--<StackPanel Orientation="Horizontal">-->
<TextBlock Text="{Binding Path=Name}"/>
<!--<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_Ilosc}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_TwrNazwa}" />-->
<!--</StackPanel>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
<GroupBox Header="Products" Grid.Row="2" Grid.Column="2">
<ListBox Name="lbProducts" ItemsSource="{Binding Source={StaticResource products}}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--<StackPanel Orientation="Horizontal">-->
<TextBlock Text="{Binding Path=Name}"/>
<!--<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_Ilosc}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_TwrNazwa}" />
</StackPanel>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
</Window>
DemoList object is binding to CollectionViewList x:Key=list.
Here is my buisiness logic i need to implement:
If checkbox is marked i need to return selected ListBoxItem to the
corresponding containers [wares, products, materials] - this logic is
working
If checkbox is unmarked i need to return ALL items
[ObservableCollection] of ALL headers to the corresponding
containers [wares, products, materials]
I'm stuck right here, can anyone suggest me a solution?
--- 2013-11-04 20:38
Sry for misunderstanding, and for my bad english.
I uploaded some screen to be more clear.
http://imgur.com/UowQrRP
As you see on the screen i need to implement behavior for checkbox.
When it is unchecked each DemoItem object must be display in one of 3 containers.
Each container is bind to CollectionViewSource.
I'm trying to display this hierarchial structure:
public interface IProgressIndicator
{
CancellationToken CancellationToken { get; }
string Name { get; set; }
}
public interface IPercentageProgressIndicator : IProgressIndicator
{
int ProgressPercentage { get; set; }
}
public interface ICountProgressIndicator : IProgressIndicator
{
int ProgressPercentage { get; }
int CurValue { get; set; }
int MaxValue { get; set; }
}
public interface ICompositeProgressIndicator : ICountProgressIndicator
{
ObservableCollection<IProgressIndicator> SubProgressItems { get; }
void MarkAsComplete(IProgressIndicator progress);
IPercentageProgressIndicator CreatePercentageIndicator();
ICountProgressIndicator CreateCountIndicator();
ICompositeProgressIndicator CreateCompositeIndicator();
}
The view shouldn't assume the hierarchial structure is in place; i.e. a regular IProgressIndicator should be displayed (using ContentControl) and using DataTemplates display other types.
So, when IProgressIndicator is of ICompositeProgressIndicator, then the root of the whole hierarchy should be a TreeView, with root tree view item displaying information (like ProgressPercentage and Name). Then children should be displayed again as IProgressIndicator and using DataTemplates choose appropriate way to view its data. Nested ICompositeProgressIndicator objects should just add another tree view item (not whole TreeView).
Here's what I came up with. I had to use Complex Hierarchical Data Templates. Also I'm using custom DataTemplateSelector, which is fairly simple:
public class ProgressIndicatorTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var element = (container as FrameworkElement);
if (item is ICompositeProgressIndicator)
return element.FindResource("CompositeProgressIndicatorTemplate") as DataTemplate;
else if (item is ICountProgressIndicator)
return element.FindResource("CountProgressIndicatorTemplate") as DataTemplate;
else if (item is IPercentageProgressIndicator)
return element.FindResource("PercentageProgressIndicatorTemplate") as DataTemplate;
return null;
}
}
Here's XAML:
<StackPanel Grid.Row="2" Margin="5" Orientation="Vertical">
<StackPanel.Resources>
<editorUtil:ProgressIndicatorTemplateSelector x:Key="progressIndicatorTemplateSelector" />
<Converters:ObjectToTypeConverter x:Key="objectTypeConverter" />
<DataTemplate x:Key="CompositeProgressIndicatorTemplateBase">
<StackPanel Orientation="Vertical">
<TextBlock Text="CompositeProgressIndicatorTemplateBase" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding SubProgressItems.Count}" />
<TextBlock Text="{Binding Converter={StaticResource objectTypeConverter}}" Margin="5" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="CompositeProgressIndicatorTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical">
<TextBlock Text="CompositeProgressIndicatorTemplateBase" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding SubProgressItems.Count}" />
<TextBlock Text="{Binding Converter={StaticResource objectTypeConverter}}" Margin="5" />
</StackPanel>
<TreeView Grid.Row="1" DataContext="{Binding}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="true"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeViewItem ItemsSource="{Binding SubProgressItems}" DataContext="{Binding}"
ItemTemplateSelector="{StaticResource progressIndicatorTemplateSelector}" IsExpanded="True">
<TreeViewItem.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel.DataContext>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type coreUtil:ICompositeProgressIndicator}}"
Path="."/>
</StackPanel.DataContext>
<TextBlock Text="CompositeProgressIndicatorTemplate" />
<ContentControl ContentTemplate="{StaticResource CompositeProgressIndicatorTemplateBase}">
<ContentControl.DataContext>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type coreUtil:ICompositeProgressIndicator}}"
Path="."/>
</ContentControl.DataContext>
</ContentControl>
</StackPanel>
</DataTemplate>
</TreeViewItem.HeaderTemplate>
</TreeViewItem>
</TreeView>
</Grid>
</DataTemplate>
<HierarchicalDataTemplate DataType="{x:Type coreUtil:ICompositeProgressIndicator}" ItemsSource="{Binding Path=SubProgressItems}">
<ContentControl ContentTemplate="{StaticResource CompositeProgressIndicatorTemplateBase}" />
</HierarchicalDataTemplate>
<DataTemplate x:Key="CountProgressIndicatorTemplate" DataType="{x:Type coreUtil:ICountProgressIndicator}">
<Grid>
<ProgressBar Height="20" Value="{Binding ProgressPercentage, Mode=OneWay}" />
<TextBlock Margin="5" HorizontalAlignment="Center" Text="{Binding ProgressPercentage, Converter={StaticResource percentageConverter}, StringFormat=P}" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="PercentageProgressIndicatorTemplate" DataType="{x:Type coreUtil:IPercentageProgressIndicator}">
<Grid>
<ProgressBar Height="20" Value="{Binding ProgressPercentage, Mode=OneWay}" />
<TextBlock Margin="5" HorizontalAlignment="Center" Text="{Binding ProgressPercentage, Converter={StaticResource percentageConverter}, StringFormat=P}" />
</Grid>
</DataTemplate>
</StackPanel.Resources>
<ContentControl Content="{Binding ProgressIndicator}" ContentTemplateSelector="{StaticResource progressIndicatorTemplateSelector}">
</ContentControl>
</StackPanel>
Here's how it looks at the moment:
There's missing DataContext for the root tree view item.
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