Dears,
I am implementing load more items to listview without a button.
My code:
public partial class DashBoardPage : ContentPage
{
ObservableCollection<string> Items;
bool isLoading;
public DashBoardPage()
{
InitializeComponent();
Items = new ObservableCollection<string>();
var listview = new ListView();
listview.ItemsSource = Items;
listview.ItemAppearing += (sender, e) =>
{
if (isLoading || Items.Count == 0)
return;
//hit bottom!
if (e.Item.ToString() == Items[Items.Count - 1])
{
LoadItems();
}
};
LoadItems();
}
public async void LoadItems()
{
isLoading = true;
HttpClient client = new HttpClient();
var response = await client.GetAsync("My Url");
string tweetJson = await response.Content.ReadAsStringAsync();
UserTweetResponse userTweetResponse = new UserTweetResponse();
if (tweetJson != "")
{
userTweetResponse = JsonConvert.DeserializeObject<UserTweetResponse>(tweetJson.ToString());
foreach (var tweet in userTweetResponse.userTweetsList)
{
Items.Add(tweet.ToString());
}
}
ListView1.ItemsSource = userTweetResponse.userTweetsList;
isLoading = false;
}
}
I refer the following link and confused with the for loop inside LoadItems():
https://montemagno.com/load-more-items-at-end-of-listview-in/
for (int i = 0; i < 20; i++)
{
Items.Add (string.Format("Item {0}", Items.Count));
}
In my case I am using itemSource property to bind the response to list view.
My model class:
public class UserTweetResponse
{
public List<UserTweetsList> userTweetsList { get; set; }
}
public class UserTweetsList
{
public int tweetId { get; set; }
public string tweetData { get; set; }
public string createdTime { get; set; }
public int commentCount { get; set; }
public int likeCount { get; set; }
public int flagCount { get; set; }
public string mediaUrl { get; set; }
public string tweetUser { get; set; }
public bool userLiked { get; set; }
public bool userFlagged { get; set; }
public bool isMediaUrlNull { get { return string.IsNullOrEmpty(mediaUrl); } }
}
How can I fix this?
Thanks in advance
You need to add your new tweets to your Items collection
public async void LoadItems()
{
isLoading = true;
HttpClient client = new HttpClient();
var response = await client.GetAsync("My Url");
string tweetJson = await response.Content.ReadAsStringAsync();
UserTweetResponse userTweetResponse = new UserTweetResponse();
if (tweetJson != "")
{
userTweetResponse = JsonConvert.DeserializeObject<UserTweetResponse>(tweetJson.ToString());
foreach (var tweet in userTweetResponse.userTweetsList)
{
Items.Add(tweet);
}
}
isLoading = false;
}
because the Observable collection is the ListView item source the new items will appear in the list.
Pasete this whole:
using System;
using System.Diagnostics;
using System.Net.Http;
using Newtonsoft.Json;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
namespace SmartTweet
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DashBoardPage : ContentPage
{
int i = 1;
bool loadMore;
ObservableCollection<UserTweetsList> Items =new ObservableCollection<SmartTweet.UserTweetsList>();
bool isLoading;
UserTweetResponse userTweetResponse;
public DashBoardPage()
{
InitializeComponent();
ListView1.ItemAppearing += (sender, e) =>
{
if (isLoading || Items!=null && Items.Count == 0)
return;
//hit bottom
if (userTweetResponse.userTweetsList!=null && userTweetResponse.userTweetsList.Count>0)
{
UserTweetsList item = userTweetResponse.userTweetsList[userTweetResponse.userTweetsList.Count - 1];
if ((e.Item as UserTweetsList).tweetId.ToString() == item.tweetId.ToString())
{
Debug.WriteLine("Enter bottom");
loadMore = true;
UserTweetsList();
}
}
};
}
protected async override void OnAppearing()
{
await UserTweetsList();
base.OnAppearing();
}
async void ButtonClicked(Object sender, EventArgs e)
{
loadMore = true;
// await UserTweetsList();
}
public async Task UserTweetsList()
{
isLoading = true;
if (loadMore)
{
i = i + 1;
}
int countInInt = i * 3;
try
{
string applicationId = "1";
string siteId = "5";
string userId = "225";
string ownedBy = "me";
string period = "before";
string count = countInInt.ToString();
DateTime dt = DateTime.Now.ToLocalTime();
string date = dt.Year.ToString() + "-" + dt.Month.ToString() + "-" + dt.Day.ToString() + " " + dt.Hour.ToString() + ":" + dt.Minute.ToString() + ":" + dt.Second.ToString() + "." + dt.Millisecond.ToString();
HttpClient client = new HttpClient();
var response = await client.GetAsync("web service url");
string tweetJson = await response.Content.ReadAsStringAsync();
Debug.WriteLine("tweetList:>" + tweetJson);
userTweetResponse = new UserTweetResponse();
if (tweetJson != "")
{
userTweetResponse = JsonConvert.DeserializeObject<UserTweetResponse>(tweetJson.ToString());
foreach (var tweet in userTweetResponse.userTweetsList)
{
if (!Items.Contains(tweet))
{
Items.Add(tweet);
}
//Items.Add(tweet.ToString());
}
}
ListView1.ItemsSource = userTweetResponse.userTweetsList;
isLoading = false;
if (userTweetResponse.userTweetsList.Count == 0)
{
//loadMoreButton.IsVisible = false;
blue_holo_circle.IsVisible = false;
blueLine.IsVisible = false;
}
else
{
//loadMoreButton.IsVisible = true;
blue_holo_circle.IsVisible = true;
blueLine.IsVisible = true;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception:>" + ex);
}
}
}
}
Related
I'm having trouble with the coding to properly listen for Firebase add or update events. My attempt below has the data loading into the Syncfusion Datagrid, but there is a weird glitch where when I click the mouse on the Datagrid and pull-down, the first record in my 4 record set gets added to the bottom of the Datagrid, showing a 5th record... if I update an element in the Datagrid, the change is not reflected in Firebase. If I add or change a value in firebase, it does not update in Datagrid. Any help to steer me in the right direction to get this to work would be appreciated. Here's the code:
the VisualStudio 2019
CookPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Chart_sample"
xmlns:gauge="clr-namespace:Syncfusion.SfGauge.XForms;assembly=Syncfusion.SfGauge.XForms"
xmlns:Syncfusion="clr-namespace:Syncfusion.SfDataGrid.XForms;assembly=Syncfusion.SfDataGrid.XForms"
mc:Ignorable="d"
x:Class="Chart_sample.Views.CookPage">
<StackLayout>
<Syncfusion:SfDataGrid x:Name="sfGrid">
</Syncfusion:SfDataGrid>
</StackLayout>
</ContentPage>
CookPage.xaml.cs
using Chart_sample.Services;
using Syncfusion.SfDataGrid.XForms;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Chart_sample.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CookPage : ContentPage
{
FirebaseHelper firebaseHelper = new FirebaseHelper();
public CookPage()
{
InitializeComponent();
// for Syncfusion DataGrid
firebaseHelper.listenForEvents();
sfGrid.ItemsSource = ViewProgramModel._returnedEvents;
sfGrid.ColumnSizer = ColumnSizer.Star;
sfGrid.AllowEditing = true;
sfGrid.NavigationMode = NavigationMode.Cell;
sfGrid.SelectionMode = Syncfusion.SfDataGrid.XForms.SelectionMode.Single;
}
}
}
FirebaseHelper.cs
using Firebase.Database;
using Firebase.Database.Query;
using System;
using System.Linq;
namespace Chart_sample.Services
{
public class FirebaseHelper
{
internal ViewProgramModel ViewProgramModel { get; set; }
FirebaseClient firebase = new FirebaseClient("https://pelletpirate.firebaseio.com/");
private readonly string ChildProgram = "ControllerData/Pellet_Pirate_1/Program";
public static IDisposable returnedEvents;
public async void listenForEvents()
{
ViewProgramModel._returnedEvents.Clear();
var programs = await firebase.Child(ChildProgram).OnceAsync<ViewProgramModel>();
for (int i = 0; i < programs.Count; i++)
{
ViewProgramModel._returnedEvents.Add(programs.ElementAt(i).Object);
}
returnedEvents = firebase.Child(ChildProgram).OrderByKey().AsObservable<ViewProgramModel>()
.Subscribe(eventReceived =>
{
if (eventReceived.EventType == Firebase.Database.Streaming.FirebaseEventType.InsertOrUpdate)
{
var found = ViewProgramModel._returnedEvents.FirstOrDefault(i => i._KEY == eventReceived.Key);
if (found == null)
{
// not in observable collection, add it
ViewProgramModel._returnedEvents.Add(eventReceived.Object);
}
else
{
// event was updated
int tempIndex = ViewProgramModel._returnedEvents.IndexOf(found);
ViewProgramModel._returnedEvents[tempIndex] = eventReceived.Object;
}
}
});
}
}
}
ViewProgrammodel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace Chart_sample
{
public class ViewProgramModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _KEy;
private string MOde;
private int TArget;
private string TRigger;
private int TRiggerVAlue;
public string _KEY
{
get { return _KEy; }
set
{
this._KEy = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("_KEY"));
}
}
public string MODE
{
get { return MOde; }
set
{
this.MOde = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MODE"));
}
}
public int TARGET
{
get { return TArget; }
set
{
this.TArget = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TARGET"));
}
}
public string TRIGGER
{
get { return TRigger; }
set
{
this.TRigger = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TRIGGER"));
}
}
public int TRIGGERVALUE
{
get { return TRiggerVAlue; }
set
{
this.TRiggerVAlue = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TRIGGERVALUE"));
}
}
public static ObservableCollection<ViewProgramModel> _returnedEvents = new ObservableCollection<ViewProgramModel>();
}
}
I edit your demo, I achieve the update, Add, delete function.
Here is running GIF.
I change your ViewProgramModel like following code. Just move the _returnedEvents to the FirebaseHelper.cs
namespace Chart_sample
{
public class ViewProgramModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _KEy;
private string MOde;
private int TArget;
private string TRigger;
private int TRiggerVAlue;
public string _KEY
{
get { return _KEy; }
set
{
this._KEy = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("_KEY"));
}
}
public string MODE
{
get { return MOde; }
set
{
this.MOde = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MODE"));
}
}
public int TARGET
{
get { return TArget; }
set
{
this.TArget = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TARGET"));
}
}
public string TRIGGER
{
get { return TRigger; }
set
{
this.TRigger = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TRIGGER"));
}
}
public int TRIGGERVALUE
{
get { return TRiggerVAlue; }
set
{
this.TRiggerVAlue = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TRIGGERVALUE"));
}
}
}
Here is FirebaseHelper.cs, Note: I achieve the update function just for the TARGET Column, I suggest your to add a Primary-key(Auto-increase) for every record in your database to achieve your search function.
public class FirebaseHelper
{
public ObservableCollection<ViewProgramModel> _returnedEvents { get; set; }
public FirebaseHelper()
{
_returnedEvents = new ObservableCollection<ViewProgramModel>();
}
// internal ViewProgramModel MyViewProgramModel { get; set; }
FirebaseClient firebase = new FirebaseClient("https://xxxxxxxxxx.firebaseio.com/");
private readonly string ChildProgram = "ControllerData/xxxxxx_Pirate_1/Program";
public static IDisposable returnedEvents;
public async Task AddViewProgramModel()
{
//new ViewProgramModel() { MODE="test", TARGET=122, TRIGGER="122", TRIGGERVALUE=333, }
await firebase
.Child(ChildProgram)
.PostAsync( new ViewProgramModel() { MODE = "test", TARGET = 122, TRIGGER = "122", TRIGGERVALUE = 333, });
GetAllData();
}
public async Task UpdateViewProgramModel(ViewProgramModel viewProgramModel , string oldValue)
{
var toUpdatePerson = (await firebase
.Child(ChildProgram)
.OnceAsync<ViewProgramModel>()).FirstOrDefault(a => a.Object.TARGET == Convert.ToInt32( oldValue));
await firebase
.Child(ChildProgram)
.Child(toUpdatePerson.Key)
.PutAsync(viewProgramModel);
GetAllData();
}
public async Task DeleteViewProgramModel(string mode)
{
var toDeletePerson = (await firebase
.Child(ChildProgram)
.OnceAsync<ViewProgramModel>()).FirstOrDefault(a => a.Object.MODE == mode);
await firebase.Child(ChildProgram).Child(toDeletePerson.Key).DeleteAsync();
GetAllData();
}
public async void GetAllData()
{
_returnedEvents.Clear();
var programs = await firebase.Child(ChildProgram).OnceAsync<ViewProgramModel>();
for (int i = 0; i < programs.Count; i++)
{
_returnedEvents.Add(programs.ElementAt(i).Object);
}
}
public async void listenForEvents()
{
_returnedEvents.Clear();
var programs = await firebase.Child(ChildProgram).OnceAsync<ViewProgramModel>();
for (int i = 0; i < programs.Count; i++)
{
_returnedEvents.Add(programs.ElementAt(i).Object);
}
//returnedEvents = firebase.Child(ChildProgram).OrderByKey().AsObservable<ViewProgramModel>()
// .Subscribe(eventReceived =>
// {
// if (eventReceived.EventType == Firebase.Database.Streaming.FirebaseEventType.InsertOrUpdate)
// {
// var found = _returnedEvents.FirstOrDefault(i => i._KEY == eventReceived.Key);
// if (found == null)
// {
// // not in observable collection, add it
// _returnedEvents.Add(eventReceived.Object);
// }
// else
// {
// // event was updated
// int tempIndex = _returnedEvents.IndexOf(found);
// _returnedEvents[tempIndex] = eventReceived.Object;
// }
// }
//});
}
}
}
Here is CookPage.xaml
<StackLayout>
<Button Text="add" Clicked="Button_Clicked"></Button>
<Button Text="delete" Clicked="Button_Clicked_1"></Button>
<Syncfusion:SfDataGrid x:Name="sfGrid" ItemsSource="{Binding _returnedEvents, Mode=TwoWay} " >
</Syncfusion:SfDataGrid>
</StackLayout>
Here is code about CookPage.cs.
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CookPage : ContentPage
{
FirebaseHelper firebaseHelper = new FirebaseHelper();
public CookPage()
{
InitializeComponent();
// for Syncfusion DataGrid
firebaseHelper.listenForEvents();
//sfGrid.ItemsSource = ViewProgramModel._returnedEvents;
BindingContext= firebaseHelper;
sfGrid.ColumnSizer = ColumnSizer.Star;
sfGrid.AllowEditing = true;
sfGrid.NavigationMode = NavigationMode.Cell;
sfGrid.AllowLoadMore = true;
sfGrid.AutoGenerateColumns = true;
//sfGrid.AutoGenerateColumnsMode= AutoGenerateColumnsMode.
sfGrid.SelectionMode = Syncfusion.SfDataGrid.XForms.SelectionMode.Single;
sfGrid.AllowPullToRefresh = true;
sfGrid.CurrentCellEndEdit += SfGrid_CurrentCellEndEdit; ;
}
private async void SfGrid_CurrentCellEndEdit(object sender, GridCurrentCellEndEditEventArgs e)
{
//throw new System.NotImplementedException();
var selectObj = sender as SfDataGrid;
RowColumnIndex index = e.RowColumnIndex;
int selectColumnIndex = index.ColumnIndex; //2
int selectRowIndex = index.RowIndex; //3
var ob=firebaseHelper._returnedEvents;
ViewProgramModel selectObject =ob[selectRowIndex-1];
var newVale = e.NewValue.ToString();
var oldeValue = e.OldValue.ToString();
//Here just judge TARGET Column, you should judge all Columns
if (selectColumnIndex == 2)
{
selectObject.TARGET = Convert.ToInt32(newVale);
}
//If you want to achieve the all Grid change function, you should judge the selectRowIndex for every change
//if (selectRowIndex==1)
//{
// selectObject.MODE = newVale;
//}else if (selectRowIndex==2)
//{
// selectObject.TARGET = Convert.ToInt32( newVale);
//}else if (selectRowIndex == 3)
//{
// selectObject.TRIGGER = newVale;
//}else if (selectRowIndex == 4)
//{
// selectObject.TRIGGERVALUE = Convert.ToInt32(newVale);
//}
await firebaseHelper.UpdateViewProgramModel(selectObject, oldeValue);
}
private async void Button_Clicked(object sender, System.EventArgs e)
{
await firebaseHelper.AddViewProgramModel();
}
private async void Button_Clicked_1(object sender, System.EventArgs e)
{
await firebaseHelper.DeleteViewProgramModel("test");
}
}
I get "unfortunately app has stopped" error after phone restart. My Phone is Oreo 8 but another phone with Nougat 7.1.1 also having the same error after phone restart. I use James Montemagnos' MyStepCounter bound services codes from GitHub with some changes in VS 2017 (Xamarin Cross-Platform App). The app is working fine if once started after phone restart with this error, else it is not counting steps and not working on the background. If I check the app in Phone Settings-General-Battery-Power saving exclusions then it works with no problems after phone restart and it is counting steps on the background without starting the app on Oreo phone. But there are no settings for battery power saving exclusions on the other phone
BootReceiver.cs
[BroadcastReceiver(Enabled = true, Exported = true, DirectBootAware = true)]
[IntentFilter(new string[] { Intent.ActionBootCompleted, Intent.ActionLockedBootCompleted, "android.intent.action.QUICKBOOT_POWERON", "com.htc.intent.action.QUICKBOOT_POWERON" })]
public class BootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
var stepServiceIntent = new Intent(context, typeof(StepService));
context.StartService(stepServiceIntent);
}
}
StepServiceBinder.cs
public class StepServiceBinder : Binder
{
StepService stepService;
public StepServiceBinder(StepService service)
{
this.stepService = service;
}
public StepService StepService
{
get { return stepService; }
}
}
StepServiceConnection.cs
public class StepServiceConnection : Java.Lang.Object, IServiceConnection
{
MainActivity activity;
public StepServiceConnection(MainActivity activity)
{
this.activity = activity;
}
public void OnServiceConnected(ComponentName name, IBinder service)
{
var serviceBinder = service as StepServiceBinder;
if (serviceBinder != null)
{
activity.Binder = serviceBinder;
activity.IsBound = true;
}
}
public void OnServiceDisconnected(ComponentName name)
{
activity.IsBound = false;
}
}
StepService.cs
public class StepServiceConnection : Java.Lang.Object, IServiceConnection
{
MainActivity activity;
public StepServiceConnection(MainActivity activity)
{
this.activity = activity;
}
public void OnServiceConnected(ComponentName name, IBinder service)
{
var serviceBinder = service as StepServiceBinder;
if (serviceBinder != null)
{
activity.Binder = serviceBinder;
activity.IsBound = true;
}
}
public void OnServiceDisconnected(ComponentName name)
{
activity.IsBound = false;
}
}
StepService.cs
[Service(Enabled = true)]
[IntentFilter(new String[] { "com.PedometerApp.StepService" })]
public class StepService : Service, ISensorEventListener, INotifyPropertyChanged
{
private SensorManager sManager;
private bool isRunning;
private long stepsToday = 0;
public bool WarningState
{
get;
set;
}
public long StepsToday
{
get { return stepsToday; }
set
{
if (stepsToday == value)
return;
stepsToday = value;
OnPropertyChanged("StepsToday");
Settings.CurrentDaySteps = value;
MessagingCenter.Send<object, long>(this, "Steps", Settings.CurrentDaySteps);
}
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
var alarmManager = ((AlarmManager)ApplicationContext.GetSystemService(AlarmService));
var intent2 = new Intent(this, typeof(StepService));
intent2.PutExtra("warning", WarningState);
var stepIntent = PendingIntent.GetService(ApplicationContext, 200, intent2, PendingIntentFlags.UpdateCurrent);
alarmManager.Set(AlarmType.Rtc, Java.Lang.JavaSystem
.CurrentTimeMillis() + 1000 * 60 * 60, stepIntent);
var warning = false;
if (intent != null)
warning = intent.GetBooleanExtra("warning", false);
Startup();
return StartCommandResult.Sticky;
}
public override void OnTaskRemoved(Intent rootIntent)
{
base.OnTaskRemoved(rootIntent);
UnregisterListeners();
var intent = new Intent(this, typeof(StepService));
intent.PutExtra("warning", WarningState);
((AlarmManager)GetSystemService(AlarmService)).Set(AlarmType.Rtc, Java.Lang.JavaSystem
.CurrentTimeMillis() + 500,
PendingIntent.GetService(this, 201, intent, 0));
}
private void Startup(bool warning = false)
{
CrunchDates(true);
if (!isRunning)
{
RegisterListeners();
WarningState = warning;
}
isRunning = true;
}
public override void OnDestroy()
{
base.OnDestroy();
UnregisterListeners();
isRunning = false;
CrunchDates();
}
void RegisterListeners()
{
sManager = GetSystemService(SensorService) as SensorManager;
sManager.RegisterListener(this, sManager.GetDefaultSensor(SensorType.StepCounter), SensorDelay.Ui);
}
void UnregisterListeners()
{
if (!isRunning)
return;
try
{
var sensorManager = (SensorManager)GetSystemService(Context.SensorService);
sensorManager.UnregisterListener(this);
isRunning = false;
}
catch (Exception ex)
{
}
}
StepServiceBinder binder;
public override Android.OS.IBinder OnBind(Android.Content.Intent intent)
{
binder = new StepServiceBinder(this);
return binder;
}
public void OnAccuracyChanged(Sensor sensor, SensorStatus accuracy)
{
//do nothing here
}
public void AddSteps(long count)
{
if (lastSteps == 0)
{
lastSteps = count;
}
newSteps = count - lastSteps;
if (newSteps < 0)
newSteps = 1;
else if (newSteps > 100)
newSteps = 1;
lastSteps = count;
CrunchDates();
Settings.TotalSteps += newSteps;
StepsToday = Settings.TotalSteps - Settings.StepsBeforeToday;
}
long newSteps = 0;
long lastSteps = 0;
public void OnSensorChanged(SensorEvent e)
{
if (lastSteps < 0)
lastSteps = 0;
var count = (long)e.Values[0];
WarningState = false;
AddSteps(count);
}
private void CrunchDates(bool startup = false)
{
if (!Utils.IsSameDay)
{
var yesterday = Settings.CurrentDay;
var dayEntry = StepEntryManager.GetStepEntry(yesterday);
if (dayEntry == null || dayEntry.Date.DayOfYear != yesterday.DayOfYear)
{
dayEntry = new StepEntry();
}
dayEntry.Date = yesterday;
dayEntry.Steps = Settings.CurrentDaySteps;
Settings.CurrentDay = DateTime.Today;
Settings.CurrentDaySteps = 0;
Settings.StepsBeforeToday = Settings.TotalSteps;
StepsToday = 0;
try
{
StepEntryManager.SaveStepEntry(dayEntry);
}
catch (Exception ex)
{
Console.WriteLine("Error {0}", ex.Message);
}
}
else if (startup)
{
StepsToday = Settings.TotalSteps - Settings.StepsBeforeToday;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
if (PropertyChanged == null)
return;
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
I took from a GitHub TkCustomMap project TK.CustomMap, and I want to call my custom service, to fill my custom list, and on ItemSelected event, from autocomplete searchBar to MapCenter it with Coordinates from my list model.
I've tried and I stopped at binding and on ItemSelect event.
Here is my MapPage:
using Xamarin.Forms;
using Xamarin.Forms.Maps;
namespace TK.CustomMap.Sample
{
public partial class SamplePage : ContentPage
{
public SamplePage()
{
//InitializeComponent();
this.CreateView();
this.BindingContext = new SampleViewModel();
}
private async void CreateView()
{
var autoComplete = new PlacesAutoComplete { ApiToUse = PlacesAutoComplete.PlacesApi.CustomList };
autoComplete.SetBinding(PlacesAutoComplete.MapSelectedCommandProperty, "MapCenter");
var newYork = new Position(40.7142700, -74.0059700);
var mapView = new TKCustomMap(MapSpan.FromCenterAndRadius(newYork, Distance.FromKilometers(2)));
mapView.IsShowingUser = true;
mapView.SetBinding(TKCustomMap.CustomPinsProperty, "Pins");
mapView.SetBinding(TKCustomMap.MapClickedCommandProperty, "MapClickedCommand");
mapView.SetBinding(TKCustomMap.MapLongPressCommandProperty, "MapLongPressCommand");
mapView.SetBinding(TKCustomMap.MapCenterProperty, "MapCenter");
mapView.SetBinding(TKCustomMap.PinSelectedCommandProperty, "PinSelectedCommand");
mapView.SetBinding(TKCustomMap.SelectedPinProperty, "SelectedPin");
mapView.SetBinding(TKCustomMap.RoutesProperty, "Routes");
mapView.SetBinding(TKCustomMap.PinDragEndCommandProperty, "DragEndCommand");
mapView.SetBinding(TKCustomMap.CirclesProperty, "Circles");
mapView.SetBinding(TKCustomMap.CalloutClickedCommandProperty, "CalloutClickedCommand");
mapView.SetBinding(TKCustomMap.PolylinesProperty, "Lines");
mapView.SetBinding(TKCustomMap.PolygonsProperty, "Polygons");
mapView.SetBinding(TKCustomMap.MapRegionProperty, "MapRegion");
mapView.SetBinding(TKCustomMap.RouteClickedCommandProperty, "RouteClickedCommand");
mapView.SetBinding(TKCustomMap.RouteCalculationFinishedCommandProperty, "RouteCalculationFinishedCommand");
mapView.SetBinding(TKCustomMap.TilesUrlOptionsProperty, "TilesUrlOptions");
mapView.SetBinding(TKCustomMap.MapFunctionsProperty, "MapFunctions");
mapView.IsRegionChangeAnimated = true;
autoComplete.SetBinding(PlacesAutoComplete.BoundsProperty, "MapRegion");
RelativeLayout _baseLayout = new RelativeLayout();
_baseLayout.Children.Add(
mapView,
Constraint.RelativeToView(autoComplete, (r, v) => v.X),
Constraint.RelativeToView(autoComplete, (r, v) => autoComplete.HeightOfSearchBar),
heightConstraint: Constraint.RelativeToParent((r) => r.Height - autoComplete.HeightOfSearchBar),
widthConstraint: Constraint.RelativeToView(autoComplete, (r, v) => v.Width));
_baseLayout.Children.Add(
autoComplete,
Constraint.Constant(0),
Constraint.Constant(0));
Content = _baseLayout;
}
}
}
Here is my PlacesAutoComplete class:
using System;
using System.Collections.Generic;
using System.Linq;
using TK.CustomMap.Api;
using TK.CustomMap.Api.Google;
using TK.CustomMap.Api.OSM;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using static TK.CustomMap.Sample.SearchBarModel;
namespace TK.CustomMap.Sample
{
public class SearchBarModel : IPlaceResult
{
public string Subtitle { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public class PlacesAutoComplete : RelativeLayout
{
public static BindableProperty BoundsProperty = BindableProperty.Create<PlacesAutoComplete, MapSpan>(
p => p.Bounds,
default(MapSpan));
// TODO: SUMMARIES
public enum PlacesApi
{
//Google,
//Osm,
//Native,
//THIS IS MY LIST!
CustomList
}
private readonly bool _useSearchBar;
private bool _textChangeItemSelected;
private SearchBar _searchBar;
private Entry _entry;
private ListView _autoCompleteListView;
private IEnumerable<IPlaceResult> _predictions;
public PlacesApi ApiToUse { get; set; }
public static readonly BindableProperty MapSelectedCommandProperty =
BindableProperty.Create<PlacesAutoComplete, Command<Position>>(
p => p.SetMap, null);
public List<SearchBarModel> myList = new List<SearchBarModel>();
public Command<Position> SetMap
{
get { return (Command<Position>)this.GetValue(MapSelectedCommandProperty); }
set { this.SetValue(MapSelectedCommandProperty, value); }
}
public double HeightOfSearchBar
{
get
{
return this._useSearchBar ? this._searchBar.Height : this._entry.Height;
}
}
private string SearchText
{
get
{
return this._useSearchBar ? this._searchBar.Text : this._entry.Text;
}
set
{
if (this._useSearchBar)
this._searchBar.Text = value;
else
this._entry.Text = value;
}
}
public new MapSpan Bounds
{
get { return (MapSpan)this.GetValue(BoundsProperty); }
set { this.SetValue(BoundsProperty, value); }
}
public PlacesAutoComplete(bool useSearchBar)
{
this._useSearchBar = useSearchBar;
this.Init();
}
public string Placeholder
{
get { return this._useSearchBar ? this._searchBar.Placeholder : this._entry.Placeholder; }
set
{
if (this._useSearchBar)
this._searchBar.Placeholder = value;
else
this._entry.Placeholder = value;
}
}
public PlacesAutoComplete()
{
this._useSearchBar = true;
this.Init();
}
private void Init()
{
OsmNominatim.Instance.CountryCodes.Add("de");
this._autoCompleteListView = new ListView
{
IsVisible = false,
RowHeight = 40,
HeightRequest = 0,
BackgroundColor = Color.White
};
this._autoCompleteListView.ItemTemplate = new DataTemplate(typeof(MapSearchCell));
View searchView;
if (this._useSearchBar)
{
this._searchBar = new SearchBar
{
Placeholder = "Search for address..."
};
this._searchBar.TextChanged += SearchTextChanged;
this._searchBar.SearchButtonPressed += SearchButtonPressed;
searchView = this._searchBar;
}
else
{
this._entry = new Entry
{
Placeholder = "Sarch for address"
};
this._entry.TextChanged += SearchTextChanged;
searchView = this._entry;
}
this.Children.Add(searchView,
Constraint.Constant(0),
Constraint.Constant(0),
widthConstraint: Constraint.RelativeToParent(l => l.Width));
this.Children.Add(
this._autoCompleteListView,
Constraint.Constant(0),
Constraint.RelativeToView(searchView, (r, v) => v.Y + v.Height));
this._autoCompleteListView.ItemSelected += ItemSelected;
this._textChangeItemSelected = false;
}
private void SearchButtonPressed(object sender, EventArgs e)
{
if (this._predictions != null && this._predictions.Any())
this.HandleItemSelected(this._predictions.First());
else
this.Reset();
}
private void SearchTextChanged(object sender, TextChangedEventArgs e)
{
if (this._textChangeItemSelected)
{
this._textChangeItemSelected = false;
return;
}
this.SearchPlaces();
}
private async void SearchPlaces()
{
try
{
if (string.IsNullOrEmpty(this.SearchText))
{
this._autoCompleteListView.ItemsSource = null;
this._autoCompleteListView.IsVisible = false;
this._autoCompleteListView.HeightRequest = 0;
return;
}
IEnumerable<IPlaceResult> result = null;
if (this.ApiToUse == PlacesApi.CustomList)
{
myList.Add(new SearchBarModel
{
Name = "Test1",
Description = "On item select, show me on map!",
Longitude = 20.4680701,
Latitude = 44.8152658
});
myList.Add(new SearchBarModel
{
Name = "Test2",
Description = "On item select, show me on map!",
Longitude = 20.4233035,
Latitude = 44.805651,
});
myList.Add(new SearchBarModel
{
Name = "Test3",
Description = "On item select, show me on map!",
Longitude = 20.456054,
Latitude = 44.8839925
});
myList.Add(new SearchBarModel
{
Name = "Test4",
Description = "On item select, show me on map!",
Longitude = 20.4328035,
Latitude = 44.8071928,
});
result = myList.OfType<IPlaceResult>().ToList<IPlaceResult>();
}
else
{
result = await OsmNominatim.Instance.GetPredictions(this.SearchText);
}
if (result != null && result.Any())
{
this._predictions = result;
this._autoCompleteListView.HeightRequest = result.Count() * 40;
this._autoCompleteListView.IsVisible = true;
this._autoCompleteListView.ItemsSource = this._predictions;
}
else
{
this._autoCompleteListView.HeightRequest = 0;
this._autoCompleteListView.IsVisible = false;
}
}
catch (Exception x)
{
// TODO
}
}
//From here my code partially works
private void ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null) return;
var prediction = (IPlaceResult)e.SelectedItem;
this.HandleItemSelected(prediction);
}
private void HandleItemSelected(IPlaceResult prediction)
{
if (this.SetMap != null && this.SetMap.CanExecute(this))
{
this.SetMap.Execute(prediction);
}
this._textChangeItemSelected = true;
this.SearchText = prediction.Description;
this._autoCompleteListView.SelectedItem = null;
this.Reset();
}
private void Reset()
{
this._autoCompleteListView.ItemsSource = null;
this._autoCompleteListView.IsVisible = false;
this._autoCompleteListView.HeightRequest = 0;
if (this._useSearchBar)
this._searchBar.Unfocus();
else
this._entry.Unfocus();
}
}
}
I am using POP3 Code for the receiving mail from mail Server It runs good on GMail and yahoo but when i am trying to connect with hotmail o ma getting error over
string response = SendCommand("STAT");
"-ERR command not expected now\r\n"
I am attaching mail code please review it and suggest me the possible solution.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;
namespace CallScreen24x7.BAL
{
public class Pop3Client : IDisposable
{
//string _host,_email,_pass;
//int port;
// string _host = ConfigurationSettings.AppSettings["host"];
public string Host { get; protected set; }
public int Port { get; protected set; }
public string Email { get; protected set; }
public string Password { get; protected set; }
public bool IsSecure { get; protected set; }
public TcpClient Client { get; protected set; }
public Stream ClientStream { get; protected set; }
public StreamWriter Writer { get; protected set; }
public StreamReader Reader { get; protected set; }
private bool disposed = false;
//public Pop3Client(string host, int port, string email, string password) : this("mail.ansitdev.com", 110, "dev#ansitdev.com", "P#ssword123", false) { }
public Pop3Client(string host, int port, string email, string password, bool secure)
{
try
{
Host = host;// ConfigurationSettings.AppSettings["host"];// "mail.ansitdev.com";
Port = port;
Email = email;// "dev#ansitdev.com";
Password = password;// ;
IsSecure = true;
}
catch (Exception ex)
{ }
}
public void Connect()
{
try
{
if (Client == null)
Client = new TcpClient();
if (!Client.Connected)
Client.Connect(Host, Port);
if (IsSecure)
{
SslStream secureStream = new SslStream(Client.GetStream());
secureStream.AuthenticateAsClient(Host);
ClientStream = secureStream;
secureStream = null;
}
else
ClientStream = Client.GetStream();
Writer = new StreamWriter(ClientStream);
Reader = new StreamReader(ClientStream);
ReadLine();
Login();
}
catch(Exception ex)
{}
}
public int GetEmailCount()
{
int count = 0;
string response = SendCommand("STAT");
if (IsResponseOk(response))
{
string[] arr = response.Substring(4).Split(' ');
count = Convert.ToInt32(arr[0]);
}
else
count = -1;
return count;
}
public Email FetchEmail(int emailId)
{
if (IsResponseOk(SendCommand("TOP " + emailId + " 0")))
return new Email(ReadLines());
else
return null;
}
public List<Email> FetchEmailList(int start, int count)
{
List<Email> emails = new List<Email>(count);
for (int i = start; i >=(start-count)+1; i--)
{
if (i >= 0)
{
Email email = FetchEmail(i);
if (email != null)
emails.Add(email);
}
}
return emails;
}
public List<MessagePart> FetchMessageParts(int emailId)
{
if (IsResponseOk(SendCommand("RETR " + emailId)))
return Util.ParseMessageParts(ReadLines());
return null;
}
public void Close()
{
try
{
if (Client != null)
{
if (Client.Connected)
Logout();
Client.Close();
Client = null;
}
if (ClientStream != null)
{
ClientStream.Close();
ClientStream = null;
}
if (Writer != null)
{
Writer.Close();
Writer = null;
}
if (Reader != null)
{
Reader.Close();
Reader = null;
}
disposed = true;
}
catch (Exception ex)
{ }
}
public void Dispose()
{
try
{
if (!disposed)
Close();
}
catch (Exception ex)
{ }
}
protected void Login()
{
try
{
if (!IsResponseOk(SendCommand("USER " + Email)) || !IsResponseOk(SendCommand("PASS " + Password))) { }
// throw new Exception("User/password not accepted");
}
catch (Exception ex)
{ }
}
protected void Logout()
{
SendCommand("RSET");
}
protected string SendCommand(string cmdtext)
{
try
{
Writer.WriteLine(cmdtext);
Writer.Flush();
return ReadLine();
}
catch (Exception ex) { return null; }
}
protected string ReadLine()
{
return Reader.ReadLine() + "\r\n";
}
protected string ReadLines()
{
StringBuilder b = new StringBuilder();
while (true)
{
string temp = ReadLine();
if (temp == ".\r\n" || temp.IndexOf("-ERR") != -1)
break;
b.Append(temp);
}
return b.ToString();
}
protected static bool IsResponseOk(string response)
{
if (response.StartsWith("+OK"))
return true;
if (response.StartsWith("-ERR"))
return false;
return true;
// throw new Exception("Cannot understand server response: " + response);
}
}
public class Email
{
public NameValueCollection Headers { get; protected set; }
public string ContentType { get; protected set; }
public DateTime UtcDateTime { get; protected set; }
public string From { get; protected set; }
public string To { get; protected set; }
public string Subject { get; protected set; }
public Email(string emailText)
{
Headers = Util.ParseHeaders(emailText);
ContentType = Headers["Content-Type"];
From = Headers["From"];
To = Headers["To"];
Subject = Headers["Subject"];
if (Headers["Date"] != null)
try
{
UtcDateTime = Util.ConvertStrToUtcDateTime(Headers["Date"]);
}
catch (FormatException)
{
UtcDateTime = DateTime.MinValue;
}
else
UtcDateTime = DateTime.MinValue;
}
}
public class MessagePart
{
public NameValueCollection Headers { get; protected set; }
public string ContentType { get; protected set; }
public string MessageText { get; protected set; }
public MessagePart(NameValueCollection headers, string messageText)
{
Headers = headers;
ContentType = Headers["Content-Type"];
MessageText = messageText;
}
}
public class Util
{
protected static Regex BoundaryRegex = new Regex("Content-Type: multipart(?:/\\S+;)" + "\\s+[^\r\n]*boundary=\"?(?<boundary>" + "[^\"\r\n]+)\"?\r\n", RegexOptions.IgnoreCase | RegexOptions.Compiled);
protected static Regex UtcDateTimeRegex = new Regex(#"^(?:\w+,\s+)?(?<day>\d+)\s+(?<month>\w+)\s+(?<year>\d+)\s+(?<hour>\d{1,2})" + #":(?<minute>\d{1,2}):(?<second>\d{1,2})\s+(?<offsetsign>\-|\+)(?<offsethours>" + #"\d{2,2})(?<offsetminutes>\d{2,2})(?:.*)$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static NameValueCollection ParseHeaders(string headerText)
{
NameValueCollection headers = new NameValueCollection();
StringReader reader = new StringReader(headerText);
string line;
string headerName = null, headerValue;
int colonIndx;
while ((line = reader.ReadLine()) != null)
{
if (line == "")
break;
if (Char.IsLetterOrDigit(line[0]) && (colonIndx = line.IndexOf(':')) != -1)
{
headerName = line.Substring(0, colonIndx);
headerValue = line.Substring(colonIndx + 1).Trim();
headers.Add(headerName, headerValue);
}
else if (headerName != null)
headers[headerName] += " " + line.Trim();
else
throw new FormatException("Could not parse headers");
}
return headers;
}
public static List<MessagePart> ParseMessageParts(string emailText)
{
List<MessagePart> messageParts = new List<MessagePart>();
int newLinesIndx = emailText.IndexOf("\r\n\r\n");
Match m = BoundaryRegex.Match(emailText);
if (m.Index < emailText.IndexOf("\r\n\r\n") && m.Success)
{
string boundary = m.Groups["boundary"].Value;
string startingBoundary = "\r\n--" + boundary;
int startingBoundaryIndx = -1;
while (true)
{
if (startingBoundaryIndx == -1)
startingBoundaryIndx = emailText.IndexOf(startingBoundary);
if (startingBoundaryIndx != -1)
{
int nextBoundaryIndx = emailText.IndexOf(startingBoundary, startingBoundaryIndx + startingBoundary.Length);
if (nextBoundaryIndx != -1 && nextBoundaryIndx != startingBoundaryIndx)
{
string multipartMsg = emailText.Substring(startingBoundaryIndx + startingBoundary.Length, (nextBoundaryIndx - startingBoundaryIndx - startingBoundary.Length));
int headersIndx = multipartMsg.IndexOf("\r\n\r\n");
if (headersIndx == -1)
throw new FormatException("Incompatible multipart message format");
string bodyText = multipartMsg.Substring(headersIndx).Trim();
NameValueCollection headers = Util.ParseHeaders(multipartMsg.Trim());
messageParts.Add(new MessagePart(headers, bodyText));
}
else
break;
startingBoundaryIndx = nextBoundaryIndx;
}
else
break;
}
if (newLinesIndx != -1)
{
string emailBodyText = emailText.Substring(newLinesIndx + 1);
}
}
else
{
int headersIndx = emailText.IndexOf("\r\n\r\n");
if (headersIndx == -1)
throw new FormatException("Incompatible multipart message format");
string bodyText = emailText.Substring(headersIndx).Trim();
NameValueCollection headers = Util.ParseHeaders(emailText);
messageParts.Add(new MessagePart(headers, bodyText));
}
return messageParts;
}
public static DateTime ConvertStrToUtcDateTime(string str)
{
Match m = UtcDateTimeRegex.Match(str);
int day, month, year, hour, min, sec;
if (m.Success)
{
day = Convert.ToInt32(m.Groups["day"].Value);
year = Convert.ToInt32(m.Groups["year"].Value);
hour = Convert.ToInt32(m.Groups["hour"].Value);
min = Convert.ToInt32(m.Groups["minute"].Value);
sec = Convert.ToInt32(m.Groups["second"].Value);
switch (m.Groups["month"].Value)
{
case "Jan":
month = 1;
break;
case "Feb":
month = 2;
break;
case "Mar":
month = 3;
break;
case "Apr":
month = 4;
break;
case "May":
month = 5;
break;
case "Jun":
month = 6;
break;
case "Jul":
month = 7;
break;
case "Aug":
month = 8;
break;
case "Sep":
month = 9;
break;
case "Oct":
month = 10;
break;
case "Nov":
month = 11;
break;
case "Dec":
month = 12;
break;
default:
throw new FormatException("Unknown month.");
}
DateTime dt = new DateTime(year, month, day, hour, min, sec);
DateTime kt = dt.AddHours(-offsetHours);
kt = kt.AddMinutes(-offsetMinutes);
return kt;
}
throw new FormatException("Incompatible date/time string format");
}
}
}
and
int page = 1;
if (Request.QueryString["page"] == null)
{
Response.Redirect("DashBoard.aspx?page=1");
Response.Flush();
Response.End();
}
else
page = Convert.ToInt32(Request.QueryString["page"]);
try
{
Email = ConfigurationSettings.AppSettings["email"].ToString();
Password = ConfigurationSettings.AppSettings["pass"].ToString();
}
catch (Exception ex)
{
Response.Redirect("DashBoard.aspx");
objentityException.ExceptionDescription = ex.Message + " " + ex.StackTrace; ;
objentityException.MethodName = "Page_Load";
objentityException.CreatedBy = Session["UserName"].ToString();
objException.InsertException(objentityException);
}
int totalEmails;
List<Email> emails;
string emailAddress;
using (Pop3Client client = new Pop3Client(Host, Port, Email, Password, false))
{
emailAddress = client.Email;
client.Connect();
totalEmails = client.GetEmailCount();
emails = client.FetchEmailList((totalEmails - ((page - 1) * 5)), NoOfEmailsPerPage);
}
int totalPages;
int mod = totalEmails % NoOfEmailsPerPage;
if (mod == 0)
totalPages = totalEmails / NoOfEmailsPerPage;
else
totalPages = ((totalEmails - mod) / NoOfEmailsPerPage) + 1;
for (int i = 0; i < emails.Count; i++)
{
AdminTransaction AT = new AdminTransaction();
DAL.Emails objEmail = new DAL.Emails();
Email email = emails[i];
int emailId = ((totalEmails - ((page - 1) * 5) - i));
TableCell noCell = new TableCell();
noCell.CssClass = "emails-table-cell";
noCell.Text = Convert.ToString(emailId);
objEmail.EmailNo = emailId;
TableCell fromCell = new TableCell();
fromCell.Text = email.From;
TableCell subjectCell = new TableCell();
subjectCell.Style["width"] = "300px";
subjectCell.Text = String.Format(DisplayEmailLink, emailId, page, email.Subject);
TableCell dateCell = new TableCell();
if (email.UtcDateTime != DateTime.MinValue)
dateCell.Text = email.UtcDateTime.ToString();
int x = AT.AddEmail(objEmail);
DataSet ds = AT.GetMailStatus(emailId);
if (ds.Tables[0].Rows.Count > 0)
{
// subjectCell.ForeColor = System.Drawing.Color.Red;
subjectCell.CssClass = "emails-table-cell";
fromCell.CssClass = "emails-table-cell";
dateCell.CssClass = "emails-table-cell";
}
else
{
subjectCell.CssClass = "emails-table-cellRead";
fromCell.CssClass = "emails-table-cellRead";
dateCell.CssClass = "emails-table-cellRead";
}
TableRow emailRow = new TableRow();
// emailRow.Cells.Add(noCell);
emailRow.Cells.Add(fromCell);
emailRow.Cells.Add(subjectCell);
emailRow.Cells.Add(dateCell);
//EmailsTable.Rows.Add(emailRow);
EmailsTable.Rows.AddAt(2 + i, emailRow);
}
if (totalPages > 1)
{
if (page > 1)
PreviousPageLiteral.Text = String.Format(SelfLink, page - 1, "Previous Page");
if (page > 0 && page < totalPages)
NextPageLiteral.Text = String.Format(SelfLink, page + 1, "Next Page");
}
EmailFromLiteral.Text = Convert.ToString(((page - 1) * NoOfEmailsPerPage) + 1);
EmailToLiteral.Text = Convert.ToString(page * NoOfEmailsPerPage);
EmailTotalLiteral.Text = Convert.ToString(totalEmails);
EmailLiteral.Text = emailAddress;
}
I've recently been re-factoring my code to move from inproc to Session State. I've created a new class that I built from the start to be serializable. I'm currently getting the 'Unable to serialize the session state.' error. However, I am able to serialize the class using JsonConvert (newtonsoft).
Are methods not allowed or something?
This is what it looks like:
[Serializable()]
public class SessionStateObject
{
public int CurrentSessionId { get; set; }
public int CurrentAssessmentId { get; set; }
public int CurrentAssessmentElementId { get; set; }
public int CurrentUserId { get; set; }
public Dictionary<string, int> AssessmentItemsIds { get; set; }
public Dictionary<string, int> SessionResponseIds { get; set; }
public List<string> AdministeredItemOrderByName;
public string LastVisitedItem;
public int? TotalAssessmentCurrentItemOrder;
public RenderablePersistanceObject RenderablePersistance;
#region formula engine section variables
public string BranchingResult { get; set; }
public string ContentOutput { get; set; }
public int CurrentItemId { get; set; }
public int VirtualWorkingItemId { get; set; }
public bool isCloneItem { get; set; }
public bool wasPreFormulaRun;
public bool wasContentOutput;
public bool wasPrefillReached;
public bool isVirtual;
public List<string> FormulaStack { get; set; }
public List<string> ItemNameTokens { get; set; }
public string serializedJSContext { get; set; }
public string CloneSourceItem { get; set; }
public int itemsAbletoFastForwardThrough { get; set; }
#endregion
private Dictionary<int, int> itemIdByMultiGroupId; //key is itemId, val is groupId
private Dictionary<int, List<int>> MultiGroupIdByItemIds; //key is groupId, val is itemId
public SessionStateObject()
{
RenderablePersistance = new RenderablePersistanceObject();
AssessmentItemsIds = new Dictionary<string, int>();
SessionResponseIds = new Dictionary<string, int>();
AdministeredItemOrderByName = new List<string>();
FormulaStack = new List<string>();
ItemNameTokens = new List<string>();
itemIdByMultiGroupId = new Dictionary<int, int>();
MultiGroupIdByItemIds = new Dictionary<int, List<int>>();
}
public void initMultiItemGroups(Assessment assessment, NetScidDbContainer dbContext)
{
List<MultiItem> assessmentMultiItems = (from multi in dbContext.MultiItems
where multi.AssessmentId == assessment.Id
select multi).ToList();
List<int> uniqueGroupIds = new List<int>();
foreach (MultiItem mItem in assessmentMultiItems)
{
itemIdByMultiGroupId.Add(mItem.ItemId, mItem.GroupId);
if (!uniqueGroupIds.Contains(mItem.GroupId))
{
uniqueGroupIds.Add(mItem.GroupId);
}
}
foreach (int groupId in uniqueGroupIds)
{
List<int> ItemIds = (from itemGroup in assessmentMultiItems
where itemGroup.GroupId == groupId
orderby itemGroup.Id ascending
select itemGroup.ItemId).ToList();
MultiGroupIdByItemIds.Add(groupId, ItemIds);
}
}
public List<int> GetItemIdsFromSingleItemId(int itemId)
{
List<int> foundItemIDs = new List<int>();
int foundGroupId = -1;
if (this.itemIdByMultiGroupId.ContainsKey(itemId))
{
foundGroupId = this.itemIdByMultiGroupId[itemId];
}
if (this.MultiGroupIdByItemIds.ContainsKey(foundGroupId))
{
foundItemIDs = this.MultiGroupIdByItemIds[foundGroupId];
}
return foundItemIDs;
}
public void nullifyRenderable()
{
this.RenderablePersistance = null;
}
public void PersistRenderable(IRenderable renderable)
{
this.RenderablePersistance = new RenderablePersistanceObject();
if (renderable is MultiItemRenderable)
{
//get list of item IDs from the multi-item lookup
this.RenderablePersistance.isMultiItem = true;
this.RenderablePersistance.primaryItemId = ((Item)((MultiItemRenderable)renderable).IndexedItems.Last()).Id;
}
else //regular renderable
{
this.RenderablePersistance.isMultiItem = false;
this.RenderablePersistance.primaryItemId = ((Item)renderable).Id;
}
}
public AssessmentRuntime StartAdministrativeSession(NetScidDbContainer dataContext, Assessment assessment, User currentUser, string pid = "1")
{
AssessmentRuntime newRuntime = new AssessmentRuntime(this, dataContext);
Session newSession = new Session();
assessment.PrepElements();
PermissionEntity rootPE = new PermissionEntity();
if (currentUser != null)
{
rootPE = PermissionEntityHelper.GetRootPermissionEnity(dataContext, currentUser);
}
else
{
rootPE = (from adminpe in dataContext.PermissionEntities
where adminpe.Name == "TelesageAdmin"
select adminpe
).FirstOrDefault();
}
newSession.Participant = (from pids in dataContext.ParticipantIdAliasLookups
where pid == pids.AliasId && pids.RootPermissionEntity.Id == rootPE.Id
select pids.Participant).FirstOrDefault();
if (newSession.Participant == null)
{
Participant newParticipant = new Participant();
ParticipantIdAliasLookup newPidAlias = new ParticipantIdAliasLookup();
newParticipant.ParticipantDataJSON = "";
newPidAlias.AliasId = pid;
newPidAlias.RootPermissionEntity = rootPE;
newParticipant.AliasLookup = newPidAlias;
newParticipant.PermissionEntities.Add(currentUser.PermissionEntity);
newParticipant.PermissionEntities.Add(rootPE);
newSession.Participant = newParticipant;
dataContext.Participants.AddObject(newParticipant);
dataContext.ParticipantIdAliasLookups.AddObject(newPidAlias);
}
newSession.Assessment = assessment;
newSession.User = currentUser;
newSession.StartTime = DateTime.Now;
newSession.PermissionEntity = currentUser.PermissionEntity;
newSession.SetSessionData("engineversion", typeof(SmartQWeb.MvcApplication).Assembly.GetName().Version.ToString());
newSession.SetSessionData("assessmentname", newSession.Assessment.Name);
newSession.SetSessionData("assessmentversion", newSession.Assessment.Version);
newSession.SetSessionData("computername", Environment.MachineName);
newSession.SetSessionData("username", currentUser.Name);
dataContext.Sessions.AddObject(newSession);
newSession.SetSessionData("dxdata", JsonConvert.SerializeObject(newRuntime.RenderedDiagnoses));
newRuntime.formulaEngine = new FixedLengthFormulaEngine(newRuntime);
SessionLog newSessionLog = new SessionLog();
dataContext.SessionLogs.AddObject(newSessionLog);
newSession.SessionLog = newSessionLog;
dataContext.SaveChanges();
initMultiItemGroups(assessment, dataContext);
this.CurrentSessionId = newSession.Id;
this.CurrentUserId = currentUser.Id;
this.CurrentAssessmentId = assessment.Id;
newRuntime.Context = new RuntimeContext(this, dataContext);
this.GetAssessmentItems(assessment); //to populate the items dict
newRuntime.formulaEngine.InitializeContext(this.AssessmentItemsIds.Keys.ToList());
newRuntime.RenderedDiagnoses = new RenderedDiagnosisModel(newRuntime.Context.AdministeredItemOrderByName);
newRuntime.Context.Logger.WriteLog("Session started with assessment: " + newRuntime.Context.Assessment.Name + " with version: " + newRuntime.Context.Assessment.Version);
newRuntime.Context.Logger.WriteLog("Session started by user: " + newRuntime.Context.CurrentUser.Name + "for participant ID: " + newSession.ParticipantId);
return newRuntime;
}
//start from a previous existing session
public AssessmentRuntime StartAdministrativeSession(NetScidDbContainer dataContext, Assessment assessment, Session previousSession, User currentUser, string pid = "", string resumefromlatest = "false")
{
AssessmentRuntime newRuntime = new AssessmentRuntime(this, dataContext);
Session newSession = new Session();
Assessment sessionAssessment = assessment;
newSession.ParticipantId = previousSession.ParticipantId;
//THE OTHER ENTITIES BESIDES THE SESSION NEED TO BE DETATCHED AND RE-ATTACHED (BY BEING ADDED TO THE NEW SESSION)
assessment.PrepElements();
newRuntime.RenderedDiagnoses = new RenderedDiagnosisModel(newRuntime.Context.AdministeredItemOrderByName);
List<Response> prevresponses = previousSession.Responses.ToList();
if (sessionAssessment == assessment)
{
foreach (Response prevresponse in prevresponses)
{
newRuntime.Context.CachedAssessmentResponses.Add(prevresponse.Item.ItemName, prevresponse);
dataContext.Detach(prevresponse);
newSession.Responses.Add(prevresponse);
}
}
else
{
//the sessionAssessment is now the more up-to-date one so the responses pulled will have to be mapped, not just detatched and copied
foreach (Response prevresponse in prevresponses)
{
Dictionary<string, FixedLengthItem> newAssessmentItemNames = AssessmentHelper.GetAssessmentItems(sessionAssessment);
if (!newAssessmentItemNames.ContainsKey(prevresponse.Item.ItemName))
continue;
Response newResponse = new Response
{
NumericValue = prevresponse.NumericValue,
Item = newAssessmentItemNames[prevresponse.Item.ItemName],
ItemName = prevresponse.Item.ItemName,
AdministeredOrder = -1,
Value = prevresponse.Value
};
newRuntime.Context.CachedAssessmentResponses.Add(newResponse.Item.ItemName, newResponse);
newSession.Responses.Add(newResponse);
}
}
newSession.SessionDataJSON = previousSession.SessionDataJSON;
//DxData
newRuntime.RenderedDiagnoses =
JsonConvert.DeserializeObject<RenderedDiagnosisModel>(newSession.GetSessionData("dxdata"));
//inc session is =2 when the the session has been resumed by
previousSession.IncSession = 2;
newSession.SetSessionData("previoussession", previousSession.Id.ToString());
newSession.Participant = previousSession.Participant;
newSession.Assessment = sessionAssessment;
newSession.User = currentUser;
newSession.PermissionEntity = currentUser.PermissionEntity;
newSession.StartTime = DateTime.Now;
dataContext.Sessions.AddObject(newSession);
dataContext.SaveChanges();
newRuntime.formulaEngine = new FixedLengthFormulaEngine(newRuntime);
initMultiItemGroups(assessment, dataContext);
newSession.SetSessionData("continuedsession", newSession.Id.ToString());
this.CurrentSessionId = newSession.Id;
this.CurrentUserId = currentUser.Id;
this.CurrentAssessmentId = assessment.Id;
this.GetAssessmentItems(assessment); //to populate the items dict
this.SetUpPreviousResponses(newSession); //populates SSO responses
newRuntime.Context = new RuntimeContext(this, dataContext);
if (newRuntime.RenderedDiagnoses != null)
newRuntime.RenderedDiagnoses.reInitAdminOrder(newRuntime.Context.AdministeredItemOrderByName);
newRuntime.formulaEngine.InitializeContext(this.AssessmentItemsIds.Keys.ToList());
return newRuntime;
}
//start from the SSO
public AssessmentRuntime ResumeSessionFromState(NetScidDbContainer dataContext)
{
AssessmentRuntime newRuntime = new AssessmentRuntime(this, dataContext);
newRuntime.formulaEngine = new FixedLengthFormulaEngine(newRuntime);
newRuntime.formulaEngine.InitializeSerializedContext(serializedJSContext);
newRuntime.Context = new RuntimeContext(this, dataContext);
if (this.CurrentAssessmentElementId != 0)
{
newRuntime.CurrentAssessmentElement = (from ae in dataContext.AssessmentElements
where ae.Id == this.CurrentAssessmentElementId
select ae).FirstOrDefault();
newRuntime.CurrentAssessmentElement.GetNewRuntime(newRuntime.Context);
}
return newRuntime;
}
private void GetAssessmentItems(Assessment assessment)
{
var fixedLengthElements = (from elements in assessment.AssessmentElements
where elements is FixedLengthBlock
select elements);
foreach (FixedLengthBlock elemblock in fixedLengthElements)
{
foreach (FixedLengthItem item in elemblock.ItemBank.Items)
{
item.aeRef = elemblock;
AssessmentItemsIds.Add(item.ItemName, item.Id);
}
}
}
private void SetUpPreviousResponses(Session newSession)
{
//put response IDs by itemname into this dictionary
SessionResponseIds = (from response in newSession.Responses
select response).ToDictionary(key => key.ItemName, value => value.Id);
}
}
And the RenderablePersistanceObject looks like this:
public class RenderablePersistanceObject
{
public int primaryItemId;
public int MultiItemGroupId;
public bool isMultiItem;
}
You can't serialize a straight Dictionary like that. You can take a look at this MSDN article for suggestions on implementing. If you don't truly need a Dictionary, perhaps List> might work better?
As Erik pointed out, it was the lack of the adorner [Serializable()] on that other object that caused the problem. Adding it solved my issue.