I'm trying to build a Pivot system based on some collections, without having to build it using code-behind.
My collection is a Dictionary<CategoriesEnum, List<object>> and I'd like to bind the PivotItem's header to the CategoriesEnum object, while its content has to be bound to the related List<objet>.
Actually I've been able to just bind the PivotItem's header but I really can't do it for the List.
Here's my current code:
(XAML)
<phone:Pivot x:Name="pivot"
ItemsSource="{Binding Categories}">
<phone:Pivot.ItemTemplate>
<DataTemplate>
<phone:PivotItem Header="{Binding}">
<ListBox ItemsSource="{Binding Path=Objects}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</phone:PivotItem>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
(C#)
public List<Categories> Categories
{
get
{
return new List<Categories>(Dictionary.Keys);
}
}
public List<object> Objects
{
get
{
return Dictionary[(Categories)pivot.SelectedItem];
}
}
I know that the Objects property will never work this way, but I can't figure out how to do this type of binding and I've not found anything online to give me a clue.
Binding the ItemsSource to a dictionary enumerates the KeyValuePairs, from which you can bind to the Key and Value properties. Let's assume the Keys in your dictionary are string and the Values are enumerables (IList):
(XAML)
<phone:Pivot x:Name="pivot" ItemsSource="{Binding MyDictionary}">
<phone:Pivot.ItemTemplate>
<DataTemplate>
<phone:PivotItem Header="{Binding Key}">
<ListBox ItemsSource="{Binding Value}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding MyName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</phone:PivotItem>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
(C#)
public IDictionary<string, IList<MyObject>> MyDictionary { get; set; }
public class MyObject
{
public string MyName { get; set; }
}
Related
So I'm trying to do a program that uses ListView (instead of CheckedListBox), and I want to get the indexes of the checked elements.
I use this as a template for the ListView:
<ListView x:Name="Content" HorizontalAlignment="Left" Height="303" Margin="10,47,0,0" VerticalAlignment="Top" Width="394" ItemClick="Content_ItemClick" SelectionChanged="Content_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Selected}"></CheckBox>
<TextBlock Text="{Binding Name}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And this is the data what it got:
public class User
{
public string Name { get; set; }
public bool Selected { get; set; }
}
How could I get back the checked elements index?
I believe your ListView's item source is bound to a backing list
<ListView ItemSource"{x:Bind UserList, Mode=OneWay}" >
<ListItem.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Selected, Mode=TwoWay} Click="Click_Handler"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListItem.ItemTemplate>
</ListView>
The UserList is List<User> which contains all your User.
Since you bind the UserList to the ListView. You could retrieve the selected item by iterating through the list and read the Selected property of each individual User.
I´m struggling with data binding here for Windows Phone 7.1. I've got a DataLoader class with an OnservableCollection of ItemList (custom class) as an attribute. Therefore, each pivot item has its own list of items. In this DataLoader, I load the data from a JSON a JSON. So far, so good.
public ObservableCollection<ItemList> PivotItem { get; set; }
Here, I store five ItemList, one for each pivot header with his corresponding list of items.
But my problem is that I want to bind this data to the XAML with a ListBox within each PivotItem.
<phone:Pivot Title="iMetrópolis" Loaded="Pivot_Loaded">
<!--Elemento Pivot 1-->
<phone:PivotItem
x:Uid="PivotItem1"
Header="Todo" Margin="14,10,10,18">
<ListBox x:Name="FirstListBox" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432" Height="78">
// I want to add textboxes binding my data
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</phone:PivotItem>
.
.
.
Thanks for the replies!!
Here is what i think you need to do , an example for databinding
<ListBox x:Name="listBox1">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Height="auto" >
<TextBlock Text="{Binding PON}" />
<TextBlock Text="{Binding PIN}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and a class for it
public class ListObject
{
public string PON { get; set; }
public string PIN { get; set; }
}
and binding real data from json
dynamic json = JsonConvert.DeserializeObject(jsondata);
var questions = new List<ListObject>();
foreach (var abc in json["jsonarray"])
{
var listOfItems = new ListObject();
listOfItems.PON= abc.object1;
listOfItems.PIN= abc.object2;
questions.Add(listOfQuestions);
}
listBox1.ItemsSource = questions;
i hope it helps reply for any comments
Say I have the following class, Employee
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public ObservableCollection<Employee> Underlings { get; set; }
}
And then I have the following XAML, bound to an ObservableCollection<Employee> MyEmployees
<ListBox ItemsSource="{Binding Path=MyEmployees}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Tag="{Binding Path=Employee.Id}">
<TextBlock Text="{Binding Path=Employee.Name}"></TextBlock>
<!-- Here's where I declare my underlings -->
<ListBox ItemsSource="{Binding Path=Employee.Underlings}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Tag="{Binding Path=Employee.Id}">
<TextBlock Text="{Binding Path=Employee.Name}"></TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This allows each employee in the collection MyEmployees to have some underlings. But those underlings are also of type employee, and could have their own underlings. How do I cater for those additional levels without making my XAML very complex?
Is there some way to declare my DataTemplate separately and allow it to be referenced within itself?
Do I have to do all this from code-behind instead?
(I realise the XAML above may not be 100% correct, its just an example)
therefore you have to use a TreeView and not a ListBox. And You have to specify a HierarchicalDataTemplate.
You could define the DataTemplate inside the ListBoxes Resources as the default template for Employees:
<ListBox ItemsSource="{Binding MyEmployees}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type myns:Employee}">
<Grid Tag="{Binding Id}">
<TextBlock Text="{Binding Name}"></TextBlock>
<ListBox ItemsSource="{Binding Underlings}" />
</Grid>
</DataTemplate>
</ListBox.Resources>
</ListBox>
I'm attempting to databind to a Windows Phone 8 Toolkit Expander view with the following XAML and C# class. I know that the DataContext is set properly because the Headers have the proper text. However, the rest of the items aren't set properly (except for the ExpanderTemplate)
<phone:PanoramaItem Header="Skill Sheet">
<ListBox Name="SkillSheet" ItemsSource="{Binding}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<toolkit:ExpanderView Header="{Binding}"
ItemsSource="{Binding}"
IsNonExpandable="False">
<toolkit:ExpanderView.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding groupName}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" LineHeight="{StaticResource LongListSelectorGroupHeaderFontSize}" />
</DataTemplate>
</toolkit:ExpanderView.HeaderTemplate>
<toolkit:ExpanderView.ExpanderTemplate>
<DataTemplate>
<TextBlock Text="Test" />
</DataTemplate>
</toolkit:ExpanderView.ExpanderTemplate>
<!--This is the area that is not getting databound-->
<toolkit:ExpanderView.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding skillNames}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding skill}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</toolkit:ExpanderView.ItemTemplate>
</toolkit:ExpanderView>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</phone:PanoramaItem>
And here are the classes that the XAML is getting bound to:
public class TreeMapSkill
{
public string skill { get; set; }
}
public class TreeMapping
{
public string groupName { get; set; }
public List<TreeMapSkill> skillNames { get; set; }
public TreeMapping()
{
skillNames = new List<TreeMapSkill>();
}
}
public class TreeMappingList
{
public List<TreeMapping> mapping { get; set; }
public TreeMappingList() { }
public TreeMappingList(Dictionary<string, List<string>> map)
: base()
{
this.mapping = new List<TreeMapping>();
foreach (string key in map.Keys)
{
TreeMapping tMap = new TreeMapping();
tMap.groupName = key;
foreach (string val in map[key])
tMap.skillNames.Add(new TreeMapSkill() { skill = val });
this.mapping.Add(tMap);
}
}
The Dictionary in the constructor is simply a list of skills associated to a specific group. I can also provide a sample object if it's needed for additional reference.
Why are you adding a ListBox inside the Expander's ItemTemplate? It is already a controls collection so you don't need a ListBox in there. Just put your DataTemplate inside.
<toolkit:ExpanderView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding skill}" />
</DataTemplate>
</toolkit:ExpanderView.ItemTemplate>
The second thing is you need to specify the property path on the binding of the ItemSource property for the expander.
<toolkit:ExpanderView Header="{Binding}"
ItemsSource="{Binding skillNames}"
IsNonExpandable="False">
I'm writing simple WPF Application and I wanted to use ListView to display List of items. My code is:
WPF.xaml
<ListView Grid.Column="0" Grid.Row="1" Margin="10,0,10,5" ItemsSource="{Binding MyCollection.Elements}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ElementDescriptions}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
WPF.xaml.cs
public MyViewModel ViewModel
{
get { return DataContext; }
set { DataContext = value; }
}
MyViewModel.cs
public OwnedCollection Elements { get; set; }
OwnedCollection.cs
public List<ElementDescriptions> ElementDescriptions { get; set; }
I'm 100% sure, that communication between View and ViewModel is correct, because displaying simple message doesn't make me troubles. Am I doing right binding in ListView?
A couple things:
First,
TextBlock Text="{Binding ElementDescriptions}"
doesn't make a lot of sense because ElementDescriptions is a collection. If you want to loop through all the ElementDescriptions in your List you should really be binding the ItemSource of the ListView to ElementDescriptions then accessing some text property of the ElementDescriptions class:
<ListView Grid.Column="0" Grid.Row="1" Margin="10,0,10,5" ItemsSource="{Binding MyCollection.ElementsElementDescriptions }">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ElementDescriptions.SomeTextField}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Second, are you using INotifyPropertyChanged so the view knows to update? More info on that here: OnPropertyChanged with a List