DataBinding a 2nd degree subclass - c#

I need help in binding data especially if the root datasource object has many subclasses and those subclasses has a subclass too. Here is my DataModel:
public class NowShowingMovies
{
public ObservableCollection<Movie> MovieCollection { get; set; }
public string Status { get; set; }
public string Total{ get; set; }
}
public class Movie
{
public string Id {get;set;}
public string Title {get;set}
public UserRating Rating {get;set;}
}
public class UserRating
{
public string UserRatingURL {get;set;}
}
And my XAML code is:
<GridView ItemsSource="{Binding MovieCollection}"
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<Border Background="White">
<TexBlock Text="{Binding Title}"/>
</Border>
<Grid Background="Black" Margin="0,0,0,0" Opacity="0.75" x:Name="grid_rating"/>
<Image Source ="{Binding Path=MovieCollection.Rating.UserRatingURL}" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
Problem is I can't make it work. UserRatingURL is not showing. I even changed it to
<Image Source ="{Binding Path=MovieCollection[0].Rating.UserRatingURL}" />
and still, no luck. What am I doing wrong? Thanks in advance!

Try to remove MovieCollection in your path.
Image Source ="{Binding Path=Rating.UserRatingURL}"

Related

Deserializing a JSON String to LongListSelector Windows Phone 8

I am working on windows phone app and I want to show some grouped JSON list item to longlist selector but I am not able to show anything in LongListSelector please help me following code I am using-:
Code Behind
public class UserInfo
{
public string service_name { get; set; }
public string uid { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public string Contact { get; set; }
public object Mutual_friend { get; set; }
public object Direct { get; set; }
public string Miles { get; set; }
}
public class ResultSearch
{
public string service { get; set; }
public List<UserInfo> user_info { get; set; }
}
public class RootObjectSearch
{
public string flag { get; set; }
public string message { get; set; }
public List<ResultSearch> result { get; set; }
}
XAML
<phone:LongListSelector Name="test"
ItemsSource="{Binding service}"
HorizontalAlignment="Left"
Height="384"
Margin="10,136,0,0"
VerticalAlignment="Top"
Width="436">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Left"
Height="301"
Margin="10,10,0,0"
VerticalAlignment="Top"
Width="436"
Background="{StaticResource PhoneAccentBrush}">
<StackPanel Orientation="Horizontal"
Height="64">
<TextBlock Text="{Binding service }"
TextWrapping="Wrap"
Foreground="Red"
Margin="10"
Width="229"
FontSize="24" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Height="64">
<TextBlock Text="{Binding fname }"
TextWrapping="Wrap"
Foreground="Red"
Margin="10"
Width="229"
FontSize="24" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Height="64">
<TextBlock Text="{Binding lname }"
TextWrapping="Wrap"
Foreground="Red"
Margin="10"
Width="229"
FontSize="24" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Height="64">
<TextBlock Text="{Binding Contact }"
TextWrapping="Wrap"
Foreground="Red"
Margin="10"
Width="229"
FontSize="24" />
</StackPanel>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
I assume that you are able to download the json as a string.
Once you have that string add Json.NET library via nuGet and then add:
List<UserInfo> userInfo = JsonConvert.DeserializeObject<List<UserInfo>>(response);
where response is the string with the json inside.
Ok, now link the List<UserInfo> to the LongListSelector:
longListSelector.ItemSource = userInfo;
where longListSelector is the x:name of the phone:LongListSelector you have previously created in XAML

WPF List inside List Binding

I am using nested ListBox for databinding,
This is my ListBox
<ListBox x:Name="lst1" ItemsSource="{Binding ListDS}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="10">
<TextBlock Text="{Binding Name}"/>
<ListBox Height="300" Width="200" ItemsSource="{Binding userFiles }" Margin="0,10" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,10,0,0">
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Print" Width="75" HorizontalAlignment="Right" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Margin="0,0,0,0" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
These are my entities
public class UsersInfo
{
public long Id { get; set; }
public string Name { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUploaded { get; set; }
public List<UsersFiles> userFiles { get; set; }
}
public class UsersFiles
{
public long Id { get; set; }
public string Name { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateDownloaded { get; set; }
}
and in my ViewModel, I have this
public List<UsersInfo> ListDS{ get; set; }
I am initializing it in my ViewModel's constructor and this is how I am populating the data
UsersInfo entity = new UsersInfo();
entity.MediaFiles = new List<UsersFiles>();
UsersFiles mFiles = new UsersFiles();
mFiles.Name = "abc";
mFiles.Id = 1
entity.Name = "User name";
entity.MediaFiles.Add(mFiles);
ListDS.Add(entity);
The problem is, ListBox is appearing blank, nothing is showing on it,even Print button.
When I added ListBoxItem in it,its showing perfectly.
Where I am doing wrong in databinding?
You have to implement INotifyPropertyChanged interface. The interface will notify the view when the property changes.
But you want your view to be notified if there is any new item in the collection so it's better to use a collection that will do that for you. Use ObservableCollection<UserInfo> to expose your ListDS.
public ObservableCollection<UserInfo> ListDS
{
get { return listDS; }
set
{
listDS = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("ListDS");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
assuming your view-model code is correct you only need to change this:
<ListBox Height="300" Width="200" ItemsSource="{Binding ListDS2}" Margin="0,10" >
to this:
<ListBox Height="300" Width="200" ItemsSource="{Binding userFiles}" Margin="0,10" >
and it will work. note the incorrect binding value !

Binding nested JSON to listbox in XAML

This is my modal,
public class main
{
public List<categories> categorieslist { get; set; }
}
public class categories
{
public int categoryId { get; set; }
public string categoryName { get; set; }
public List<pdf> pdfdocs { get; set; }
public List<video> videoFiles { get; set; }
}
public class pdf
{
public string URL { get; set; }
public string language { get; set; }
public string createdDate { get; set; }
public bool isFavorite { get; set; }
public bool isRead { get; set; }
}
Im using JSON.NET to deserialize
main mainobj = JsonConvert.DeserializeObject<main>(App.hello);
I need to display list of PDF's for a selected category,
Im using LINQ to filter that particular category, I am unable to bind the PDF list..
pdf.ItemsSource = App.mainobj.categorieslist.Where(i => i.categoryId.Equals(s));
<ListBox x:Name="pdf" Margin="0,0,0,363" ItemsSource="{Binding}" Foreground="White">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding pdf.URL}" Foreground="White"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox ItemsSource="{Binding categorieslist}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding categoryId }" FontSize="20" />
<ItemsControl ItemsSource="{Binding pdf}" Margin="0 20 0 0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Blue" BorderThickness="2">
<TextBlock Text="{Binding URL }" FontSize="20" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl ItemsSource="{Binding videoFiles}" Margin="0 20 0 0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="2">
<TextBlock Text="{Binding URL}" FontSize="20" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>

Bind function to button in ListView using delegate in model

I'm new to C# and I'm trying to bind a function in each item of my collection to a button for that item. My collection is a List<AssessmentItem>, where each AssessmentItem is the following:
public class AssessmentItem
{
public string Label { get; set; }
public string Explanation { get; set; }
public string ResourceURL { get; set; }
public BitmapImage Icon { get; set; }
public RunFixer Fixer { get; set; }
}
public RunFixer Fixer is the delegate I want to bind to the button for that particular AssessmentItem. Here is the DataTemplate I'm using to accomplish my plans:
<DataTemplate x:Key="AssessmentListTemplate">
<Grid Margin="0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Label}" FontSize="16" VerticalAlignment="Center" Grid.Column="0" FontWeight="Bold" Margin="15,0,0,0"/>
<Button Grid.Column="2" Margin="0,0,10,0">
<Image Source="{Binding Icon}" Width="64" Height="64"/>
</Button>
</Grid>
</DataTemplate>
How do I bind the <Button>'s Click handler to my RunFixer delegate? I tried {Binding Fixer}, which didn't work. I also changed Fixer to a MouseButtonEventHandler, but that didn't work either.
Thank you for your time looking at this! I don't mind being educated.
Additions
The RunFixer delegate is declared with
public delegate void RunFixer();
Final Code
For my personal documentation and for other's satisfaction, I'm posting the result that worked well for me:
public class AssessmentItem
{
public string Label { get; set; }
public string Explanation { get; set; }
public string ResourceURL { get; set; }
public BitmapImage Icon { get; set; }
public RunFixer Fixer { get; set; }
DelegateCommand _fixerCommand = null;
public ICommand FixerCommand
{
get
{
if (_fixerCommand == null)
{
_fixerCommand = new DelegateCommand(() => Fixer());
}
return _fixerCommand;
}
}
}
And in the DataTemplate:
<DataTemplate x:Key="AssessmentListTemplate">
<Grid Margin="0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Label}" FontSize="16" VerticalAlignment="Center" Grid.Column="0" FontWeight="Bold" Margin="15,0,0,0"/>
<Button Grid.Column="2" Margin="0,0,10,0" Command="{Binding FixerCommand}">
<Image Source="{Binding Icon}" Width="64" Height="64"/>
</Button>
</Grid>
</DataTemplate>
Hope this helps!
You can't bind a function to a button. But you can bind command object to a button's Command property. In order to do this you need to modify your class:
public class AssessmentItem
{
public string Label { get; set; }
public string Explanation { get; set; }
public string ResourceURL { get; set; }
public BitmapImage Icon { get; set; }
public RunFixer Fixer { get; set; }
ICommand _fixerCommand = new UICommand();
public ICommand FixerCommand {
get
{
_fixerCommand = _fixerCommand ?? new DelegateCommand<object>((o)=>
{var f = Fixer;
if(f != null) f();});
return _fixerCommand;}
}
}
I'm using DelegateCommand class which is a part of Prism library which can be downloaded here
Then you're modifying your data template to bind to this FixerCommand property
<Button Grid.Column="2" Margin="0,0,10,0" Command ="{Binding FixerCommand}">
<Image Source="{Binding Icon}" Width="64" Height="64"/>
</Button>
You can't bind the "Click" event of a button because it is not a dependency property (in this case it is a routed event). Luckily, WPF gives us the "Command" property (which is a dependency property) for a button!
Your binding will look like:
Command="{Binding RunFixerCommand}"
Your data object will expose an ICommand property which will return a command object that calls "RunFixer". A great example of a reusable and easy to use generic command class can be found in this blog post.
Sample (in your AssessmentItem class):
public ICommand RunFixerCommand {get; private set;}
public AssessmentItem()
{
RunFixerCommand = new DelegateCommand((p) => RunFixer());
}

Get Object properties of selected list item

I have a listbox that has a listsource that is a list of 'results' objects. The results class looks like this:
public class Result
{
public string GUID { get; set; }
public string __invalid_name__I { get; set; }
public string FN { get; set; }
public string DOB { get; set; }
public string SEX { get; set; }
public string SN { get; set; }
public string __invalid_name__U { get; set; }
public string TYPE { get; set; }
//Gender icon path associated with result
public string SexIcon { get; set; }
}
And this is what my listbox looks like in the xaml code:
<ListBox
Height="517"
HorizontalAlignment="Left"
Margin="12,84,0,0"
Name="searchList"
VerticalAlignment="Top"
Width="438"
SelectionChanged="SearchList_SelectedEvent">
<!-- What each listbox item will look like -->
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Sex, Converter={StaticResource SexToSourceConverter}}" Visibility="Visible" />
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Name="FirstName" Text="{Binding FN}" FontSize="28" Margin="0,0,10,0"/>
<TextBlock Name="LastName" Text="{Binding SN}" FontSize="28" />
</StackPanel>
<TextBlock Text="{Binding DOB}" FontSize="24" />
<!-- Line Stroke="#FF04863C" StrokeThickness="3" X1="100" Y1="100" X2="300" Y2="100" / -->
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
So my question is, (and what I'm really struggling with) is how does one for instance get the value of the GUID property of the selected Item (which is basically a results object)?
(searchList.SelectedItem as Result).GUID

Categories