UI in xamarin for items with variable number of rows - xamarin

Suppose I have the following classes:
class Person
{
public string Name { get; set; }
public IList<Expense> Expenses { get; set; }
public int Total => Expenses.Sum(o => o.Amount);
}
class Expense
{
public string ExpenseName { get; set; }
public int Amount { get; set; }
}
And then I have a collection of persons: IList<Person> Persons
How can I design an XAML page in Xamarin, in order to show something like this?:

You can use Label to display the variable number of expenses, In the end of item, add "\n" to wrap.
The running screenshot like following img.
First, here is my layout.
<StackLayout>
<ListView x:Name="EmployeeView" HasUnevenRows="True"
ItemsSource="{Binding Persons}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label FontSize="Large" Text="{Binding Name}"></Label>
<Label FontSize="Body" Text="{Binding ExpensesList}"></Label>
<Label FontSize="Body" Text="{Binding Total}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Here is layout's background code.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
this.BindingContext =new MyViewModel();
}
}
Here is my viewModel. I add some testing data to viewModel, And add "\n" to the end of every expense's text.
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace App83
{
internal class MyViewModel
{
public ObservableCollection<Person> Persons { get; set; }
public MyViewModel()
{
Persons = new ObservableCollection<Person>();
ObservableCollection<Expense> expenses= new ObservableCollection<Expense>();
expenses.Add(new Expense() { Amount=1, ExpenseName="name1" });
expenses.Add(new Expense() { Amount = 1, ExpenseName = "name2" });
expenses.Add(new Expense() { Amount = 1, ExpenseName = "name3" });
expenses.Add(new Expense() { Amount = 1, ExpenseName = "name4" });
ObservableCollection<Expense> expenses2 = new ObservableCollection<Expense>();
expenses2.Add(new Expense() { Amount = 1, ExpenseName = "name1" });
ObservableCollection<Expense> expenses3 = new ObservableCollection<Expense>();
string expensesList1="";
for (int i = 0; i < expenses.Count; i++)
{
if(i== (expenses.Count - 1))
{
expensesList1 += expenses[i].ToString();
}
else
{
expensesList1 += expenses[i].ToString() + "\n";
}
}
string expensesList2 = "";
for (int i = 0; i < expenses2.Count; i++)
{
if (i == (expenses2.Count - 1))
{
expensesList2 += expenses2[i].ToString();
}
else
{
expensesList2 += expenses2[i].ToString() + "\n";
}
}
string expensesList3 = "";
for (int i = 0; i < expenses3.Count; i++)
{
if (i == (expenses3.Count - 1))
{
expensesList3 += expenses3[i].ToString();
}
else
{
expensesList3 += expenses3[i].ToString() + "\n";
}
}
Person per =new Person( ) { Name="test1", Expenses= expenses, expensesList= expensesList1 };
Person per2 = new Person() { Name = "test2", Expenses = expenses2,expensesList= expensesList2 };
Person per3 = new Person() { Name = "test3", Expenses = expenses3, expensesList = expensesList3 };
Persons.Add(per);
Persons.Add(per2);
Persons.Add(per3);
}
}
}
Here is my edited Model. AddExpensesList perperty to show variable number of expenses, keep the ExpenseName and Amountin the same line, I override the ToString method.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace App83
{
public class Person: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public Person() {
}
public string Name { get; set; }
public string expensesList;
public string ExpensesList
{
set
{
if (expensesList != value)
{
expensesList = value;
OnPropertyChanged("Image");
}
}
get
{
return expensesList;
}
}
public IList<Expense> Expenses { get; set; }
public int Total => Expenses.Sum(o => o.Amount);
}
public class Expense
{
public string ExpenseName { get; set; }
public int Amount { get; set; }
public override string ToString()
{
return ExpenseName+" "+Amount;
}
}
}

Within your DataTemplate you can add another View that supports the ItemSource property.
So it could be another ListView, CollectionView or a StackLayout. The latter is great if you know that you won't have too many items under expense as otherwise it might cause serious app performance issues.
So inside of your DataTemplate just add
<CollectionView ItemSource={Binding Expenses}>
<DataTemplate>
//your UI goes here
.
.
.

Related

Display Dates from a List in a CalendarView Xamarin

I have a CalendarioView from this Xamarin.Plugin.Calendar nuget package.
I've been following this tutorial, and I want to have the same result. Instead of assigning the EventCollection list manually, as in the example, I have my List.
How to fill it in the EventCollection? I've searched and didn't find anything that worked.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:c ="clr-namespace:Minha_Carteira_Hospitalar.Controls"
x:Class="Minha_Carteira_Hospitalar.Views.PlanoReceita"
xmlns:controls="clr-namespace:Xamarin.Plugin.Calendar.Controls;assembly=Xamarin.Plugin.Calendar">
<controls:Calendar
Events="{Binding Events}"
>
<controls:Calendar.EventTemplate>
<DataTemplate>
<StackLayout Padding="15,0,0,0">
<Label
Text="{Binding Name}"
FontAttributes="Bold"
FontSize="Medium" />
</StackLayout>
</DataTemplate>
</controls:Calendar.EventTemplate>
</controls:Calendar>
MVVM code
public EventCollection Events;
public ObservableCollection<Plans> myPlans= new ObservableCollection<Plans>();
public ObservableCollection<Plans> MyPlans
{
get => myPlans;
set => myPlans= value;
}
public MyPlansViewModel()
{
Events = new EventCollection();
}
public ICommand LoadingMyPlans
{
get
{
return new Command(async () =>
{
try
{
List<Plans> tmp = await App.Database.GetMyPlans();
foreach(var item in tmp)
{
MyPlans.Clear();
tmp.ForEach(i => MyPlans.Add(i));
Events.Add(item.DatePlan, MyPlans);
}
}
catch (Exception ex)
{
await Application.Current.MainPage.DisplayAlert("Error", ex.Message, "OK");
}
});
}
}
I am not sure where you use the LoadingMyPlans for. I make a simple example about how to fill your own list into EventCollection for your reference.
The same Xaml as yours.
Model:
public class Plans
{
public DateTime dateTime { get; set; }
public List<Plan> plans { get; set; }
}
public class Plan
{
public string Name { get; set; }
public string Desc { get; set; }
}
ViewModel:
public class CalendarViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(storage, value))
{
return false;
}
storage = value;
OnPropertyChanged(propertyName);
return true;
}
public EventCollection Events { get; set; }
public ObservableCollection<Plans> plans { get; set; }
public CalendarViewModel()
{
plans = new ObservableCollection<Plans>()
{
new Plans(){ dateTime=DateTime.Now, plans=new List<Plan>() { new Plan() { Name = "Plan_A", Desc = "aaaaa" }, new Plan() { Name = "Plan_A2", Desc = "aaaaa2" } }},
new Plans(){ dateTime=DateTime.Now.AddDays(5), plans=new List<Plan>() { new Plan() { Name = "Plan_B", Desc = "bbbbb" }, new Plan() { Name = "Plan_B2", Desc = "aaaaa2" } }},
new Plans(){ dateTime=DateTime.Now.AddDays(-3), plans=new List<Plan>() { new Plan() { Name = "Plan_C", Desc = "ccccc" }}}
};
Events = new EventCollection();
foreach (var item in plans)
{
Events.Add(item.dateTime, item.plans);
}
}
}
Code behind:
public Page2()
{
InitializeComponent();
this.BindingContext = new CalendarViewModel();
}

Xamarin C# Databinding on ViewModels with multiple foreign key relations in datamodels: Picker and labels

Oke here is the context: I have a Xamarin Application that connects to ASP.NET rest service. Currently I am working on the databinding on my views
There is a certain Data model called prestatie which has a foreingn Key Reference to the Trainer model class and another that foreign key reference to the Getuigschrift Class.
public class Prestatie : INotifyPropertyChanged
{
[Key]
private Guid _PrestatieID;
public Guid PrestatieID
{
get => _PrestatieID;
set
{
_PrestatieID = value;
RaisePropertyChanged(nameof(PrestatieID));
}
}
private string _Rekeningnummer;
public string Rekeningnummer
{
get => _Rekeningnummer;
set
{
_Rekeningnummer = value;
RaisePropertyChanged(nameof(Rekeningnummer));
}
}
private string _Rijksregisternummer;
public string Rijksregisternummer
{
get => _Rijksregisternummer;
set
{
_Rijksregisternummer = value;
RaisePropertyChanged(nameof(Rijksregisternummer));
}
}
[ForeignKeyAttribute("Trainer")]
public Guid? TrainerID
{
get;
set;
}
public Trainer Trainer
{
get;
set;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Trainer Class:
public class Trainer : Persoon
{
private Guid _TrainerID;
public Guid TrainerID
{
get => _TrainerID;
set
{
_TrainerID = value;
RaisePropertyChanged(nameof(TrainerID));
}
}
public ICollection<Prestatie> Prestaties
{
get;
set;
}
public Getuigschrift Getuigschriften
{
get;
set;
}
private Guid _GetuigschriftID;
public Guid? GetuigschriftID
{
get => _GetuigschriftID;
set
{
_GetuigschriftID = (Guid)value;
RaisePropertyChanged(nameof(GetuigschriftID));
}
}
}
Now I got two ViewModels setup fto represent this data, one for an overview and the second for the Details/Editing/adding. Databinding of items is on the viewmodels, so in Theory I should make these relations up in my view models but I am uncertain on how to do this. At one hand I just need to have some labels back in the ItemViewModel, and the other hand I need sort of comobox/list/picker for the data input to just get the Foregin Key.
Solutions I have tried it something like this, but that does not seem to work.
Xamarin ListView MVVM DataBinding
Here is a small snippet of my viewmodels, I cant post more because of the character limit.
public class PrestatieViewModel : BaseViewModel
{
private ObservableCollection<Prestatie> _prestaties;
private readonly IPrestatieDataService _prestatieDataService;
private readonly INavigationService _navigationService;
public ObservableCollection<Prestatie> Prestaties
{
get => _prestaties;
set
{
_prestaties = value;
OnPropertyChanged("Prestaties");
}
}
public class PrestatieDetailViewModel : BaseViewModel
{
private Prestatie _selectedPrestatie;
private readonly IPrestatieDataService _prestatieDataService;
private readonly INavigationService _navigationService;
public Prestatie SelectedPrestatie
{
get => _selectedPrestatie;
set
{
_selectedPrestatie = value;
OnPropertyChanged(nameof(SelectedPrestatie));
}
}
You can bind the picker's selectedItem with trainer so you could pick and set the value.
Here are the code you could refer to
xmal:
<ContentPage.BindingContext>
<local:PeopleViewModel/>
</ContentPage.BindingContext>
<CollectionView x:Name="mycol">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="100,* "
RowDefinitions="*,*">
<Label Text="{Binding Name}" BackgroundColor="LightBlue"/>
<Picker x:Name="mypicker" Grid.Column="1" Title="Select a Trainer"
TitleColor="Red"
ItemsSource="{Binding pgs}"
ItemDisplayBinding="{Binding Name}"
SelectedItem="{Binding Trainer}">
</Picker>
<Label Text="Trainer:" Grid.Row="1" Grid.Column="0" BackgroundColor="AliceBlue"/>
<Label
Grid.Row="1"
Grid.Column="1"
Text="{Binding Trainer.Name}"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
viewmodel:
public class PeopleViewModel:INotifyPropertyChanged
{
string name;
People trainer;
public List<People> pgs { get; private set; } = new List<People>{new People{Name="Trainer1" },
new People{ Name="Trainer2"} ,
new People{ Name="Trainer3"} };
public string Name {
get { return name; }
set { if (name != value)
{ name = value;
OnPropertyChanged();
}
} }
public People Trainer
{
get { return trainer; }
set
{
if (trainer != value)
{
trainer = value;
OnPropertyChanged();
}
}
}
#region INotifyPropertyChanged
void OnPropertyChanged(string name=null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
#endregion
public event PropertyChangedEventHandler PropertyChanged;
}}

how to create a view model and rest api call in xamarin forms in MVVM

I have an api URL here which provides the response below.
Json
{"status":200,"message":"Operation done successfully","data":{"enableNext":false,"products":[{"image":"http://bresa.lazyhost.in/upload/product/1/Tjtqr8.jpg","id":1,"code":"PROi6v8X5261","name":"Spandex Stretch Lounge Sofa with Couch Seat Cover SlipCover","description":"nice sofa , very comfortable for sitting in Living room","tags":"chairs, sofa, ","price":"1000.00","quantity":100,"images":["http://bresa.lazyhost.in/upload/product/1/Tjtqr8.jpg"]}]}}
The model class for above response is below.
CarouselModel
namespace CameliaMaison.Models
{
public partial class CarouselModel
{
[JsonProperty("status")]
public long Status { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("data")]
public List<CarouselData> Carouseldata { get; set; }
}
public partial class CarouselData
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("path")]
public string Path { get; set; }
}
}
The ViewModel
namespace CameliaMaison.ViewModels
{
public class CarouselImagesViewModel
{
private List<CarouselData> items;
public List<CarouselData> Items
{
get { return items; }
set
{
items = value;
}
}
public CarouselImagesViewModel()
{
var responseObj = MyHTTP.GetApiData().Result;
foreach(CarouselData item in responseObj){
Items.Add(item);
}
}
}
public class MyHTTP
{
public static async Task<List<CarouselData>> GetApiData()
{
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync("http://bresa.lazyhost.in/api/banners");
CarouselModel categoriesData = new CarouselModel();
var content = await response.Content.ReadAsStringAsync();
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
categoriesData = JsonConvert.DeserializeObject<CarouselModel>(await response.Content.ReadAsStringAsync());
}
return categoriesData.Carouseldata;
}
}
}
I need to parse the JSON and store in Model Object and populate the data in the listview via MVVM.However, there seems to be something wrong with the implementation. I am unable to figure out and the content page class is below.
ProductsListPage.xaml.cs
public partial class ProductsListPage : ContentPage
{
public ProductsListPage()
{
InitializeComponent();
}
}
ProductsListPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:constants="clr-namespace:CameliaMaison;assembly=CameliaMaison"
x:Class="CameliaMaison.Views.ProductsListPage"
Title="Employee List">
<ListView x:Name="ListView">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="ABC" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
First you must have a button on your view page.
<Button Command = "{Binding GetInfoCommand}" />
Than you must create a view-model. Something like this :
public class CarouselModel: INotifyPropertyChanged
{
//get a reference from the another class where you make the call to get the json
Tasks ts = new Tasks();
List<CarouselData> _carouseldata ;
public List<CarouselData> CarouselData
{
get { return _carouseldata ; }
set
{
if (value == _carouseldata ) return;
_carouseldata = value;
OnPropertyChanged();
}
}
public ICommand GetIInfoComand
{
get
{
return new Command(async()=>
{
CarouselData= await _apiServices.GetInfo();
});
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Than in your tasks.cs class you must consume the call where you get the json. This simple. :)
==edit==
In your view you must replace your textcell.Something like this :
<ListView x:Name="ListView">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name }" />
</DataTemplate>
</ListView.ItemTemplate>
Also you get a reference of your view model and place it before the listview :
<ContentPage.BindingContext>
<CarouselModel/>
</ContentPage.BindingContext>

ListView stops updating after few seconds when I bind a ListView to ReactiveList

I am developing an app with Xamarin.Forms, trying to leverage ReactiveUI, but Xamarin.Forms ListView does not behave as expected.
The test setup is an Entry field which I input values into. I subscribe to changes on the ReactiveList and add the value to a ListView.
The problem: The ListView updates for a few seconds and then just stops.
Console still logs inputs.
Sample code below:
<!-- xaml layouts omitted for brevity -->
<Entry x:Name="searchbox" HorizontalOptions="FillAndExpand"
Text="{Binding SearchQuery, Mode=TwoWay}"
/>
<ListView x:Name="ResultView">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Address}"></TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel + SearchResult class:
public class SearchViewModel : ReactiveObject
{
public ReactiveList<SearchResult> SearchResults { get; set; }
private string searchQuery;
public string SearchQuery
{
get { return searchQuery; }
set { this.RaiseAndSetIfChanged(ref searchQuery, value); }
}
public ReactiveCommand<List<SearchResult>> Search { get; set; }
public SearchViewModel()
{
// Set up our ListView data list
this.SearchResults = new ReactiveList<SearchResult>();
this.SearchResults.ChangeTrackingEnabled = true;
Search = ReactiveCommand.CreateAsyncTask(async _ => {
return await GenerateSearchResultAsync(this.SearchQuery);
});
Search.Subscribe(results => {
SearchResults.Clear(); // just replace output every time
SearchResults.AddRange(results);
// output results to console
results.ForEach(r => Console.WriteLine(r.Address));
});
// this used to contain a condition I removed for brevity
this.WhenAnyValue(x => x.SearchQuery).InvokeCommand(this, x => x.Search);
}
// create a new result list and return it, async code removed for demo-simplicity
private static async Task<List<SearchResult>> GenerateSearchResultAsync(string value)
{
var rv = new List<SearchResult>();
rv.Add(new SearchResult(value + " " + DateTime.Now.ToString("hh:mm:ss.FFFF")));
return rv;
}
}
public class SearchResult
{
private string address;
public SearchResult(string s)
{
this.Address = s;
}
public string Address { get; set; }
}
This seems to be a bug when WeakReferences are mistakenly collected during GC.
I'm not knowledgable enough to do the debugging, but some other smart guys did:
https://github.com/reactiveui/ReactiveUI/issues/806
https://bugzilla.xamarin.com/show_bug.cgi?id=31415 (open xamarin bug report)
Workaround:
Add this class to your project:
public class ReactiveObservableCollection<T> : ReactiveList<T>
{
public ObservableCollection<T> ObservableCollection { private set; get; }
public ReactiveObservableCollection()
{
this.ObservableCollection = new ObservableCollection<T>();
ItemsAdded.Subscribe(ObservableCollection.Add);
ItemsRemoved.Subscribe((x) => ObservableCollection.Remove(x));
}
}
and use it instead of the ReactiveList:
public class ViewModel : ReactiveObject {
public ReactiveObservableCollection<SearchResult> SearchResults { set; get; }
public ViewModel()
{
// use ReactiveObservableCollection instead of ReactiveList
this.SearchResults = new ReactiveObservableCollection<SearchResult>()
{
ChangeTrackingEnabled = true
};
}
Also, make sure to use the .ObservableCollection property on the collection as ItemSource (instead of just the collection)!
this.ResultView.ItemsSource = viewModel.SearchResults.ObservableCollection;
instead of
this.ResultView.ItemsSource = viewModel.SearchResults;
This should solve the problem.
HTH!

WP7 listbox binding not working properly

A noob error for sure (I started yesterday afternoon developing in WP7), but I'm wasting a lot time on it.
I post my class and a little part of my code:
public class ChronoLaps : INotifyPropertyChanged
{
private ObservableCollection<ChronoLap> laps = null;
public int CurrentLap
{
get { return lap; }
set
{
if (value == lap) return;
// Some code here ....
ChronoLap newlap = new ChronoLap()
{
// Some code here ...
};
Laps.Insert(0, newlap);
lap = value;
NotifyPropertyChanged("CurrentLap");
NotifyPropertyChanged("Laps");
}
}
public ObservableCollection<ChronoLap> Laps {
get { return laps; }
set
{
if (value == laps) return;
laps = value;
if (laps != null)
{
laps.CollectionChanged += delegate
{
MeanTime = Laps.Sum(p => p.Time.TotalMilliseconds) / (Laps.Count * 1000);
NotifyPropertyChanged("MeanTime");
};
}
NotifyPropertyChanged("Laps");
}
}
}
MainPage.xaml.cs
public partial class MainPage : PhoneApplicationPage
{
public ChronoLaps History { get; private set; }
private void butStart_Click(object sender, EventArgs e)
{
History = new ChronoLaps();
// History.Laps.Add(new ChronoLap() { Distance = 0 });
LayoutRoot.DataContext = History;
}
}
MainPage.xaml
<phone:PhoneApplicationPage>
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid Grid.Row="2">
<ScrollViewer Margin="-5,13,3,36" Height="758">
<ListBox Name="lbHistory" ItemContainerStyle="{StaticResource ListBoxStyle}"
ItemsSource="{Binding Laps}"
HorizontalAlignment="Left" Margin="5,25,0,0"
VerticalAlignment="Top" Width="444">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Lap}" Width="40" />
<TextBlock Text="{Binding Time}" Width="140" />
<TextBlock Text="{Binding TotalTime}" Width="140" />
<TextBlock Text="{Binding Distance}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
Problem is that when I add one or more items to History.Laps collection, my listbox is not refreshed and these items don't appear.
But if I remove comment on // History.Laps.Add(new ChronoLap()... line, this item appear and so every other inserted later.
More: if I remove that comment and then write History.Laps.Clear() (before or after setting binding) binding is not working anymore. It's like it gets crazy if collection is empty.
I really don't understand the reason...
UPDATE AND SOLUTION:
If i move
History = new ChronoLaps();
LayoutRoot.DataContext = History;
from butStart_Click to public MainPage() everything works as expected.
Can someone explain me the reason?
Actually I see no point of having a separate class for ChronoLaps. Here is how I modified the code for MainPage.xaml.cs and everything seems to be working for me.
public partial class MainPage : PhoneApplicationPage
{
public ObservableCollection<ChronoLap> Laps { get; set; }
public double MeanTime { get; set; }
// Constructor
public MainPage()
{
InitializeComponent();
Laps = new ObservableCollection<ChronoLap>();
Laps.CollectionChanged += delegate
{
MeanTime = Laps.Sum(p => p.Time.TotalMilliseconds) / (Laps.Count * 1000);
};
DataContext = this;
Loaded += (s, e) =>
{
Laps.Add(new ChronoLap() {Time = TimeSpan.FromSeconds(1000)});
Laps.Add(new ChronoLap() {Time = TimeSpan.FromSeconds(1000)});
Laps.Add(new ChronoLap() {Time = TimeSpan.FromSeconds(1000)});
};
}
}
Try binding DataContext and ItemSource for listbox..
How i have done is..
<ListBox x:Name="AppList" Background="White" DataContext="{Binding DisplayItem}" SelectionChanged="AppList_SelectionChanged" Height="500" Width="auto">
<ListBox.ItemTemplate>
<DataTemplate>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And i dont know if it will help but still i will just post the code that i am using..
ItemList.cs
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
namespace AppHouseLibrary
{
public class ItemList : IComparable
{
private string _name;
public string WidgetName
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int ID
{
get;
set;
}
private BitmapImage _Icon;
public BitmapImage Icon
{
get
{
return _Icon;
}
set
{
_Icon = value;
}
}
//public string arrow { get; set; }
public BitmapImage arrow { get; set; }
public int CompareTo(ItemList other)
{
return this.WidgetName.CompareTo(other.WidgetName);
}
}
}
I have a UIManager.cs class in which am refreshing the data before i load it on the UI to the user..
using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;
using System.Collections.Generic;
using StirLibrary.com.mportal.data.bean;
using com.mportal.utils;
using StirLibrary.com.mportal.utils;
namespace StirLibrary.com.UI
{
public class UIManager : INotifyPropertyChanged
{
private static UIManager instance = null;
private static string TAG = "UIManager";
BitmapImage arrowImage = Utils.returnImage(ImageUtils.ARROW);
public List<ItemList> data = new List<ItemList>();
public static UIManager getInstance()
{
if (instance == null)
{
instance = new UIManager();
}
return instance;
}
private ObservableCollection<ItemList> _displayItem = new ObservableCollection<ItemList>();
public ObservableCollection<ItemList> DisplayItem
{
get
{
return _displayItem;
}
}
private UIManager()
{
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String PropertyName)
{
if (null != PropertyChanged)
{
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
public WidgetBean[] serviceBeanList = null;
public WidgetBean[] wheelBeanList = null;
public WidgetBean getServiceWidgetBean(int selectedIndex)
{
try
{
if (serviceBeanList != null)
{
return serviceBeanList[selectedIndex];
}
}
catch (Exception e)
{
Logger.log(TAG, e.Message);
}
return null;
}
public WidgetBean getWheelWidgetBean(int selectedIndex)
{
try
{
if (wheelBeanList != null)
{
return wheelBeanList[selectedIndex];
}
}
catch (Exception e)
{
Logger.log(TAG, e.Message);
}
return null;
}
public void DisplayCatalog(string[] ServiceDisplayName, string[] WheelDisplayName, BitmapImage[] ServiceIcons, WidgetBean[] ServiceBeanList, WidgetBean[] WheelBeanList)
{
try
{
DisplayItem.Clear();
string disp1 = string.Empty;
string name = ServiceDisplayName[0];
wheelBeanList = WheelBeanList;
serviceBeanList = ServiceBeanList;
for (int i = 0; i < ServiceDisplayName.Length; i++)
{
WidgetBean bean = serviceBeanList[i];
if (bean.isCategory())
{
DisplayItem.Add(new ItemList { WidgetName = ServiceDisplayName[i], Icon = ServiceIcons[i], arrow = arrowImage });
}
else
{
DisplayItem.Add(new ItemList { WidgetName = ServiceDisplayName[i], Icon = ServiceIcons[i] });
}
}
NotifyPropertyChanged("UI");
}
catch (Exception e)
{
Logger.log(TAG,e.Message);
}
}
public void DisplayCatalog(string[] displayName, BitmapImage[] icons, WidgetBean[] beanArray)
{
try
{
serviceBeanList = beanArray;
DisplayItem.Clear();
for (int i = 0; i < displayName.Length; i++)
{
WidgetBean bean = serviceBeanList[i];
if (bean.isCategory())
{
DisplayItem.Add(new ItemList { WidgetName = displayName[i], Icon = icons[i], arrow = arrowImage });
}
else
{
DisplayItem.Add(new ItemList { WidgetName = displayName[i], Icon = icons[i] });
}
}
NotifyPropertyChanged("UI");
}
catch (Exception e)
{
Logger.log(TAG,e.Message);
}
}
}
}

Resources