c# deserialize json array and data binding - c#

I have trouble to deserialize this json file. I want to bind the "favoriteSongs" array to my view in xaml and display all the informations in a longlistselector.
{
"_id": "56fd864ff28510694a6a7b5e",
"addFavorites": {
"favoriteSongs": [
{
"_id": "570aeb89869a0520e0d0365c",
"title": "get lucky",
"album": "random access memory",
"primaryArtist": "daft punk",
"artist": "570ae933cd7d1072b430ea51",
"primaryGenre": "electro",
"genre": "570ae933cd7d1072b430ea52",
"duration": "3m31s",
"year": 2013
},
{ ... }
]
}
In my view model im using an observablecollection to add the informations from the json, here the "getFavoriteSongsModel" is my RootObject
for (int i = 0; i < count; i++)
{
getFavoriteSongsModel = JsonConvert.DeserializeObject<GetFavoriteSongsModel>(e.Result);
getFavoriteSongs.Add(new GetFavoriteSongsModel()
{
Id = getFavoriteSongsModel.Id,
Favorites = getFavoriteSongsModel.Favorites
});
I tried to use this pattern with another observablecollection that points to a class with a list of all the infomations i need but it crashes everytime. I don't know how to use the "Favorites" variable, i know it is populated but i can't display what i want in the xaml.
<Grid>
<phone:LongListSelector x:Name="MainLongListSelector" Margin="0,0,-12,0" ItemsSource="{Binding getFavoriteSongs}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" >
<TextBlock Text="{Binding FavoriteSongs.Album}" Style="{StaticResource PhoneTextBlockBase}"/>
<TextBlock Text="{Binding FavoriteSongs.Title}" Style="{StaticResource PhoneTextBlockBase}"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>

I have create a sample Code on base of my understanding.
I have Created three classes on based of Json string from json2csharp, which is very useful to create classes on based of Json string.
Three classes are as following
public class FavoriteSong
{
public string _id { get; set; }
public string title { get; set; }
public string album { get; set; }
public string primaryArtist { get; set; }
public string artist { get; set; }
public string primaryGenre { get; set; }
public string genre { get; set; }
public string duration { get; set; }
public int year { get; set; }
}
public class AddFavorites
{
public ObservableCollection<FavoriteSong> favoriteSongs { get; set; }
}
public class MainClass
{
public string _id { get; set; }
public AddFavorites addFavorites { get; set; }
}
I have just use your string as json and on base I have create this samle.
Following code will deserialize json string
public MainClass objMainClass { get; set; }
string strJson = "{\"_id\": \"56fd864ff28510694a6a7b5e\",\"addFavorites\": {\"favoriteSongs\": [{\"_id\": \"570aeb89869a0520e0d0365c\",\"title\": \"get lucky\",\"album\": \"random access memory\",\"primaryArtist\": \"daft punk\",\"artist\": \"570ae933cd7d1072b430ea51\",\"primaryGenre\": \"electro\",\"genre\": \"570ae933cd7d1072b430ea52\",\"duration\": \"3m31s\",\"year\": 2013}]}}";
objMainClass = new MainClass();
objMainClass = JsonConvert.DeserializeObject<MainClass>(strJson);
MainLongListSelector.DataContext = objMainClass.addFavorites;
and binding in XAML is as following
<phone:LongListSelector
x:Name="MainLongListSelector"
Margin="0,0,-12,0"
ItemsSource="{Binding favoriteSongs}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel
Margin="0,0,0,17">
<TextBlock
Text="{Binding album}"
Style="{StaticResource PhoneTextBlockBase}" />
<TextBlock
Text="{Binding title}"
Style="{StaticResource PhoneTextBlockBase}" />
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
Hope so it will be helpful to you.

Related

WPF TreeView binding multiple different dictionaries in different levels and sorting them by TKey

I have these Models:
public class CustomerGroup
{
public string GroupName { get; set; }
public string GroupKey { get; set; }
}
public class Customer
{
public string GroupKey { get; set; }
public string CustomerKey { get; set; }
public string CustomerName { get; set; }
// and more irrelevant stuff for my question...
}
public class ConstructionSite
{
public string CustomerKey { get; set; }
public string GroupeKey { get; set; }
public string ConstructionSiteName { get; set; }
// and more irrelevant stuff for my question...
}
And i have these Dictionaries:
public class CustomerGroupList : List<CustomerGroup>
{
// Methods for Serialization etc.
}
public class CustomersDictionary : SortedDictionary<string, List<Customer>> // TKey is GroupKey
{
// Methods for Serialization etc.
}
public class ConstructionSiteDictionary : SortedDictionary<string, List<ConstructionSite>> // TKey is customerKey
{
// Methods for Serialization etc.
}
So the customer's dictionary contains the groupKey as TKey and a list of customers for this group as value.
And the construction sites dictionary contains the CustomerKey as TKey and a list of construction sites for this customer as value.
And the Dictionaries are stored in a static class
Now I want to bind these dictionaries as source of an treeview and it should look like this:
-CustomerGroupOne
-CustomerOne
-Construction site A
-Construction site B
-CustomerTwo
-ConSite C
-GroupTwo
-CustomerThree
So I found a solution to Bind the data, BUT I can't figure out how to get the list from the dictionary with the key of the upper node's key.
I Expected it would work like this:
<TreeView x:Name="treeView" ItemsSource="{Binding Source={x:Static dataServices:DataProviderService.CustomerGroupsList}}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate>
<Label Content="{Binding GroupName}"/>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Source={x:Static dataServices:DataProviderService.CustomersDictionary[GroupKeyOfUpperNodesCurrentGroup]}}">
<Label Content="{Binding CustomerName}"/>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Source={x:Static dataServices:DataProviderService.ConstructionSiteDictionary[CustomerKeyOfUpperNodesCorrentCustomer]}}">
<TextBlock Text="{Binding ConstructionSiteName}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
I hope anyone can help me. Thanks for any help!
Sorry for the bad English...
I'm going to school right now and just started with C# for a little more than one year...
As the name TreeView implies, the control displays a tree data structure. But a dictionary is a flat collection of key-value pairs. Obviously the Dictionary is from data source. You have to convert the dictionary to the proper hierarchical data structure. It's recommended to have your data entities reflect the hierarchical data structure. A hierarchical data structure can be achieved by adding child collections to the data models:
Hierarchical data structure
public class CustomerGroup
{
// Define a child collection
public ObservableCollection<Customer> Customers { get; set; }
public string GroupName { get; set; }
public string GroupKey { get; set; }
}
public class Customer
{
// Define a child collection
public ObservableCollection<ConstructionSite> ConstructionSites { get; set; }
public string GroupKey { get; set; }
public string CustomerKey { get; set; }
public string CustomerName { get; set; }
// and more irrelevant stuff for my question...
}
public class ConstructionSite
{
public string CustomerKey { get; set; }
public string GroupeKey { get; set; }
public string ConstructionSiteName { get; set; }
// and more irrelevant stuff for my question...
}
DataSourceViewModel.cs
class DataSourceViewModel : INot6ifyPropertyChanged
{
public ObservableCollection CustomerGroups { get; }
public DataSourceViewModel()
{
this.CustomerGroups = new ObservableCollection()
{
new CustomerGroup
{
CustomerGroupName = "CustomerGroupOne",
Customers = new Customer
{
CustomerName = "CustomerOne",
ConstructionSites = new ConstructionSite {ConstructionSiteName = "Construction site A"}
}
}
};
}
MainWindow.xaml
Define HieratchicalDataTemplates to display the structure and
assign DataSourceViewModel to the DataContext as non-static binding source.
<Window>
<Window.DataContext>
<DataSourceViewModel />
</Window.DataContext>
<TreeView ItemsSource="{Binding CustomerGroups}">
<TreeView.Resources>
<!-- Root node -->
<HierarchicalDataTemplate DataType={x:Type CustomerGroup}"
ItemsSource="{Binding Customers}">
<TextBlock Text="{Binding GroupName}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType={x:Type Customer}"
ItemsSource="{Binding ConstructionSites}">
<TextBlock Text="{Binding CustomerName}" />
</HierarchicalDataTemplate>
<!-- Leaf node -->
<DataTemplate DataType={x:Type ConstructionSite}>
<TextBlock Text="{Binding ConstructionSitesName}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Window>

Binding DataGrid to an ObservableCollection which is a property of a ListBox's SelectedItem

In my application I have a ListBox and a DataGrid.
I'm trying to bind the DataGrid to an ObservableCollection which is a property of the returned SelectedItem from the ListBox - this doesn't work and I don't understand why. Output console doesn't print any errors.
The ObservableCollection is of type ReportItem, and it can contain instances of TextReportItem, which inherits from ReportItem.
XAML:
<ListBox x:Name="listBox" HorizontalAlignment="Left" Margin="10,10,0,36.667" Width="119" ItemsSource="{Binding ReportItems}" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel HorizontalAlignment="Left" Height="274" Margin="134,10,0,0" VerticalAlignment="Top" Width="375" >
<StackPanel.Resources>
<Style x:Key="ControlBaseStyle" TargetType="{x:Type Control}">
<Setter Property="Margin" Value="0, 10, 0, 0" />
</Style>
</StackPanel.Resources>
<DataGrid Height="190" VerticalAlignment="Bottom" DataContext="{Binding ElementName=listBox, Path=SelectedItem.TItems}" />
</StackPanel>
ViewModel:
public class MainViewModel
{
public ObservableCollection<ReportItem> ReportItems { get; set; }
public object SelectedReportItem { get; set; }
public MainViewModel()
{
ReportItems = new ObservableCollection<ReportItem>();
ReportItems.Add(Example);
}
// line below is for debugging purposes
public TextReportItem Example = new TextReportItem() { Name = "ti1", DataFile = "ti1.txt"};
}
ReportItem:
public class ReportItem
{
public int Id { get; set; }
public string Name { get; set; }
public string DataFile { get; set; }
}
TextReportItem and TextParcel:
public class TextReportItem : ReportItem
{
public ObservableCollection<TextParcel> TItems { get; set; }
public TextReportItem()
{
TItems = new ObservableCollection<TextParcel>();
}
}
public class TextParcel
{
public char Delimiter { get; set; }
public string LineExp { get; set; }
public string Result { get; set; }
public string IgnoreLine { get; set; }
public int DesiredResultIndexInLine { get; set; }
}
I think the mere DataContext doesn't tell the DataGrid what it has to show. You have to give it an ItemsSource. Maybe you could try something like that:
<DataGrid
DataContext="{Binding ElementName=listBox, Path=SelectedItem}"
ItemsSource="{Binding TItems}" />
I believe that the DataContext of a DataGrid expects an IEnumerable, and not a single instance of an object. When you set the source to a single instance of a ReportItem, you're not passing it anything that it can iterate to construct it's rows.
If you make the necessary changes and give that a yank, you should be golden :)
you can use select index change method instead
protected void GridView_SelectedIndexChanged(object sender, EventArgs e){
string value = null;
value = GridView1.SelectedRow.Cells(2).Text.ToString();
}

displaying images from server in a list box

On Windows Phone 8 I have a page that loads user places. Each place consists of name and image name. I then search for the image in the storage and display it. All of that is viewed in a list box using data binding. I do not know how to set the image source in the data binding. Should I make an extra variable of type bit image in the Place class, or in the get of string image name should I call the function which returns a bit image?
Here is the Place class:
class Place
{
public string id { get; set; }
public string user_id { get; set; }
public string name { get; set; }
public string radius { get; set; }
public string longitude { get; set; }
public string latitude { get; set; }
public string image { get; set; }
public string thumbnail { get; set; }
public async Task<placesobj> getUserPlaces(string userId)
{
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string> ("id", userId),
new KeyValuePair<string, string> ("data", "all_places")
};
var serverData = serverConnection.connect("places.php", pairs);
placesobj json = JsonConvert.DeserializeObject<placesobj>(await serverData);
if (json != null)
return json;
else
return null;
}
public class placesobj
{
public List<Place> places { get; set; }
}
}
}
And here is the XAML for the list box:
<ListBox Grid.Row="1" ItemsSource="{Binding places}" Margin="0,10,0,0" >
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Margin="10,0,10,8">
<StackPanel Orientation="Horizontal" Margin="10,0,10,8">
<TextBlock Text="{Binding name}" TextWrapping="Wrap" FontSize="50" />
<Image Source="{Binding }"
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Try this. I think this will be fine . this is working for me.
reference
Image source is expecting a uri . so better give this as uri
<Image Source="{Binding Image}"/>
public Uri Image { get; set; }

Producing a hierarchy of treeview in xaml

This seems like a common question but I have not been able to get it working from the answers of other questions.
I have a company, which has multiple projects, and each project can have multiple tasks. The company class contains some metadata and also a list of projects that it owns, the project class also has some metadata and a list of tasks it has. What I'm trying to do is to display this hierarchy in a tree view. I have made a sample object of a company which has 2 projects and project1 has 2 tasks. The tree view should only display one company at a time, so the root treeviewitems are the projects.
Heres my attempt at the problem, but nothing is displayed.
<TreeView ItemsSource="{Binding listOfProjects}" Margin="10" Height="200">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding listOfTasks}" DataType="{x:Type local:Task}">
<TreeViewItem Header="{Binding name}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding name}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
How do I go about making it correct? What should I bind to ItemsSource? For the TreeViewItem headers, how do I let it know which field to bind? At the moment, I have {Binding name}, but how do I differentiate between where its coming from (because project has a field 'name', and so does task).
I will be extending the hierarchy further (a task can have multiple parts and so on) but I'm assuming that each additional level would be done the same as the first 2.
edit: here my company, project and task classes.
class Company
{
public List<Project> listOfProjects;
public string name { get; set; }
private int companyID { get; set; }
public Company()
{
companyID = 0;
name = "Default";
listOfProjects = new List<Project>();
}
public Company(string inName)
{
companyID = 0;
name = inName;
listOfProjects = new List<Project>();
}
}
class Project
{
private int projID { get; set; }
public string name { get; set; }
public DateTime startDate { get; set; }
public DateTime endDate { get; set; }
public string region { get; set; }
private int companyID { get; set; }
public List<Task> listOfTasks;
public Project()
{
projID = 0;
name = "Default";
startDate = new DateTime();
endDate = new DateTime();
region = "Default";
companyID = 0;
listOfTasks = new List<Task>();
}
public Project(string inName)
{
projID = 0;
name = inName;
startDate = new DateTime();
endDate = new DateTime();
region = "Default";
companyID = 0;
listOfTasks = new List<Task>();
}
}
Tasks atm doesnt have anything in it except a constructor. It has 2 fields, projectID and name.
Your hierarchical data template override your treeview. You must rename listofProject and listofTask to same name. Therefore you create Interface or Class.Then implement Company,Project,Task from this interface.
public interface ITreeItem
{
string Name { get; }
List<ITreeItem> childs { get; }
}
public class Company : ITreeItem
{
public string Name
{
get { return name; }
}
public List<ITreeItem> childs
{
get { return listofProjects; }
}
}
public class Project : ITreeItem
{
public string Name
{
get { return name; }
}
public List<ITreeItem> childs
{
get { return listofTask; }
}
}
public class Task : ITreeItem
{
public string Name
{
get { return name; }
}
public List<ITreeItem> childs
{
get { return null; }
}
}
Then your template is
<HierarchicalDataTemplate ItemsSource="{Binding childs}" DataType="{x:Type local:ITreeItem}">
<TreeViewItem Header="{Binding Name}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding Name}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
So the top level will all be of type "project", and all branches will be of type "task"? You can use multiple HierarchicalDataTemplates like this:
<StackPanel.Resources>
<sdk:HierarchicalDataTemplate x:Key="TaskTemplate"
ItemsSource="{Binding Path=Childs}">
<TextBlock FontStyle="Italic" Text="{Binding Path=Name}" />
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key="ProjectTemplate"
ItemsSource="{Binding Path=ListOfTasks}"
ItemTemplate="{StaticResource TaskTemplate}">
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold" />
</sdk:HierarchicalDataTemplate>
</StackPanel.Resources>
And then declare your treeview like this ...
<sdk:TreeView ItemsSource="{Binding MyProjectList}"
ItemTemplate="{StaticResource ProjectTemplate}" x:Name="myTreeView" />

Listbox in other Listbox, Itemsource, Binding

I would like to know How to refresh our ListBox item.
I tried OnPropertyChanged method, ObservableCollection, but it didn't work. I tried set again the itemsource property, so that worked, but now I have got 2 ListBox and now it's complicated. It's a wp7 project there is the main interface. You can see I have 2 listbox
<ListBox Name="lsbNameDays" ItemsSource="ComplexNameDays">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding NameDay.Name}" FontSize="50"/>
<ListBox ItemsSource="ComplexNameDays.FacebookFriends" x:Name="asdf">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Lastname}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
there is the properties:
List<SelectedNameDays> complexNameDays;
public List<SelectedNameDays> ComplexNameDays
{
get { return complexNameDays; }
set
{
complexNameDays = value;
OnPropertyChanged("ComplexNameDays");
}
}
public class SelectedNameDays : Notifier
{
NameDay _nameday;
public NameDay NameDay
{
get { return _nameday; }
set { _nameday = value; OnPropertyChanged("NameDay"); }
}
public List<FacebookFriend> FacebookFriends { get; set; }
public SelectedNameDays()
{
_nameday = new NameDay();
}
}
public class FacebookFriend
{
public long Id { get; set; }
public string Name { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Birthday { get; set; }
public string Gender { get; set; }
public Uri Picture { get; set; }
}
The begining of the code is correct, that works, because when the Constructor set the datas I set retry the itemsource of lbsNameDays, but i cant find the "asdf" listbox, i can't set their datas again.
so the 2 main question are that.
1. how can i fire the property changed if that, and the observable collecton doesn't works.
2. how can I use asdf listbox in the datatemplate
thank the answer, and I sorry my grammer mistakes
Your Bindings won't work, because you dont use the right syntax:
ItemsSource="ComplexNameDays"
should be
ItemsSource="{Binding ComplexNameDays}"
The second binding is also wrong:
ItemsSource="ComplexNameDays.FacebookFriends"

Categories