Trying to display data in a DisplayActionSheet - c#

I have a collectionview pulling all the data from a class Terms in a contentpage. I have a SelectionChanged event handler that will pull up all the courses that make up the selected term.
private async void termsCollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(e.CurrentSelection != null)
{
Terms terms = (Terms)e.CurrentSelection.FirstOrDefault();
await Navigation.PushAsync(new TermView(terms));
}
}
Then I have for Edit Term
private async void EditTerm_Clicked(object sender, EventArgs e)
{
}
Basically I need 2 different selections inside of one page. 1 for the courses that make up a term and 1 for editing all the information for that term. Just throwing this piece out there in case somebody has a better way of doing it.
I stumbled across this method
await DisplayActionSheet()
I was wondering if there was a way to display a list of all the Terms I currently have to choose from. Once a term is selected, pass the termId through the EditTerms(termId) to view all the info for that selected term. All the videos I have seen are passing in strings to select.
I wouldn't mind writing out the terms are strings to select but Terms is scalable that can grow or shrink over time. So manual strings isn't really plausible.
EDIT - I have a method in my Database class (using sqlite) to get terms but I'm not able to figure out the syntax for accessing it.
public static async Task <IEnumerable<Terms>> GetTerms()
{
await Init();
var terms = await _db.Table<Terms>().ToListAsync();
return terms;
}

if this is your list of terms
var terms = await _db.Table<Terms>().ToListAsync();
you can build an array using something like this (assuming that Term has a Name property, adjust accordingly)
var termarray = terms.Select(t => t.Name).ToArray();

Related

How to detect which item the user clicked in a ListBox win forms [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
What I am struggling doing, is
figuring out a wild card for SelectedItems[]
I want a var uploadDir to be based off of the SelectedItem.
the way I currently am going about it I feel is just repetitive code and possible a better way of going about.
Listbox1
Also it will not let me set x as null and use that in SelectedItems[x]
Current Debug Code
private void button1_Click(object sender, EventArgs e)
{
if (ReportPeriod == "Daily Call Data")
{
MessageBox.Show(ReportPeriod);
}else if(ReportPeriod == "Weekly Call Data")
{
MessageBox.Show(ReportPeriod);
}
}
public string ReportPeriod;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
int x;
ReportPeriod = listBox1.SelectedItems[x].ToString();
}
Any suggestion is greatly appreciated.
I am working a small program for work, to update our KPI dashboards via excel templates and VLOOKUPS.
So what I have is a user interface that will allow the manager to select the type of data that they will be loading from a ListBox
Ex: Daily Call Data, Daily CSAT Data, Weekly Call Data, etc..
they then browse for the downloaded csv file and press update
the csv is moved and renamed as well as the old file renamed to previous day,month,year etc.
Quick PSEUDO Code
int x;
ReportPeriod = listBox1.SelectedItems[x].ToString();
if(ReportPeriod == "Daily Call Data"){
try{
string UploadDir = "C:\folder\daily\filename.xls";
more code...
}catch(Exception){
More code...
}
}
Else If (ReportPeriod == "Weekly Call Data"{
try{
string uploadDir = "C:\folder\weekly\filename.xls";
}
}
What I'm needing is to be able to do is either detect which item was selected and assign that to ReportPeriod and create IF and ELSE IF statements from there or if I could possibly assign a value to the Listbox Items (such as a static dir path).
I just don't know how to go about grabbing the selected item from the users mouse click.
You don't grab the selected item from the mouse click per se; the list box will tell you which items are selected with the relevant property:
If you only want the user to choose one item from the list, set the SelectionMode to One, then access the SelectedItem property
If you want the user to choose multiple reports and run them all but save them to a common csv, set the selection mode to something that allows multi and then loop through the SelectedItems collection running the report for each
I presume you loaded your list Items collection with strings (text). It's important to note that you'll get them back as object so you'll probably need to cast or .ToString() before you compare with a string to find out what was selected
As for when is a good time in the code to get the value, your button click suits me:
private void button1_Click(object sender, EventArgs e)
{
var rp= listbox1.SelectedItem.ToString();
if (rp == "Daily Call Data")
{
MessageBox.Show("day");
}else if(rp == "Weekly Call Data")
{
MessageBox.Show("week");
}
}

Reload Data every time I navigate to Page

I have this Windows Phone Page where I load data through the standard ViewModel scope.
public Profile()
{
InitializeComponent();
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (!App.PersonalizedViewModel.IsDataLoaded)
{
App.PersonalizedViewModel.LoadData();
}
}
This works fine. However when I navigate to this page from some other page the data is still the same. I mean the LoadData() method should recheck updated data right? Please suggest.
EDIT:
My PersonalizedViewModelClass:
public class PersonalizationViewModel: INotifyPropertyChanged
{
public PersonalizationViewModel()
{
this.favorites = new ObservableCollection<ItemViewModel>();
this.Bar = new ObservableCollection<Bars>();
}
public ObservableCollection<ItemViewModel> favorites { get; private set; }
public ObservableCollection<Bars> Bar { get; private set; }
private string _sampleProperty = "Sample Runtime Property Value";
public string SampleProperty
{
get
{
return _sampleProperty;
}
set
{
if (value != _sampleProperty)
{
_sampleProperty = value;
NotifyPropertyChanged("SampleProperty");
}
}
}
public bool IsDataLoaded
{
get;
private set;
}
/// <summary>
/// Creates and adds a few ItemViewModel objects into the Items collection.
/// </summary>
public async void LoadData()
{
favorites.Clear();
try
{
var query = ParseObject.GetQuery("Favorite")
.WhereEqualTo("user", ParseUser.CurrentUser.Username);
IEnumerable<ParseObject> results = await query.FindAsync();
this.favorites.Clear();
foreach (ParseObject result in results)
{
string venue = result.Get<string>("venue");
string address = result.Get<string>("address");
string likes = result.Get<string>("likes");
string price = result.Get<string>("price");
string contact = result.Get<string>("contact");
this.favorites.Add(new ItemViewModel { LineOne=venue, LineTwo=address, LineThree=likes, Rating="", Hours="", Contact=contact, Price=price, Latitude="", Longitude="" });
}
if (favorites.Count == 0)
{
// emailPanorama.DefaultItem = emailPanorama.Items[1];
MessageBox.Show("You do not have any saved cafes. Long press a cafe in main menu to save it.");
}
}
catch (Exception exc)
{
MessageBox.Show("Data could not be fetched!", "Error", MessageBoxButton.OK);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Implementation of PersonalizedViewModel:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
await App.PersonalizedViewModel.LoadData();
user_tb.Text = ParseUser.CurrentUser.Username;
if (NavigationContext.QueryString.ContainsKey("item"))
{
var index = NavigationContext.QueryString["item"];
var indexParsed = int.Parse(index);
mypivot.SelectedIndex = indexParsed;
}
if (NavigationService.BackStack.Any())
{
var length = NavigationService.BackStack.Count() - 1;
var i = 0;
while (i < length)
{
NavigationService.RemoveBackEntry();
i++;
}
}
}
I don't see the problem, however, I think you need to narrow in on the problem.
First off, you are calling LoadData from 2 places. 1 from MainPage_Load and 1 from OnNavigatedTo. In MainPage_Load it is conditional and in OnNavigatedTo it is always being called. I suggest that you get to a single path through the code instead of 2 so that you don't get different experiences. I personally recommend (without knowing all the details) that you call load data from OnNavigatedTo instead of MainPage_Load. If you want to do it conditionally that is fine but if you are loading the data from memory, it really is unnecessary as you won't improve performance anymore than a few milliseconds. Also, if you are not loading from memory, you may not want to load it conditionally because the underlying data may have changed. In either case, the choice to load data or not should be moved out of the view and into the data layer (but that is for another post).
Once you have a single path chosen (i.e. calling LoadData from MainPage_Load or OnNavigatedTo) you should use your debugger. Put a break point in LoadData method and if it is being called appropriately, then your problem is more specific than your posted question. Here are some questions to think about (you may want to start from the last question and work your way backward)
Questions:
Is LoadData being called appropriately?
Does ParseObject have the correct data?
Is the ParseUser...UserName set properly?
Is the foreach being executed the proper # of times (i.e. does the result of your query have the right # of items?)
Couple Code Tips completely unrelated to this problem:
Single Path through code. Don't call LoadData from more than one place.
Don't call favorites.clear() twice in the same method. (it is called twice in LoadData)
Consistent naming. favorites is lowercase but Bar is upper case.
User proper data types. On your ItemViewModel you have Hours, Latitude, and Longitude. You have them as strings. These clearly are not strings. Also, you should not set them to empty. Empty means they have been set to a value. Emtpy is a valid value. Null means not set. To keep your objects clean and accurate you want to be accurate in how you set things and then deal appropriately with the impact. If you really really want them to be initialized to empty strings, then at least do it in the constructor of ItemViewModel so that every caller doesn't have to know how to initialize every property. I guarantee this is leading to buggy code if you continue using this practice.
Please take the comments as constructive criticism not criticism. I know many people don't like to hear these things but the teams I lead write bugs until they start following these types of guidelines.
Good luck,
Tom
Instead of defining this
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
into constructor i.e. Profile I would suggest remove this code from Constructor and add it into your OnNavigatedTo. so the data will load after navigation
Your OnNavigatedTo Method looks like follows
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
Might be your problem will solve.
Edit
Try this query
var results = (from find in ParseObject.GetQuery("Favorite").WhereEqualTo("user", ParseUser.CurrentUser.Username) select find);
Tried this:
var query = from favorite in ParseObject.GetQuery("Favorite")
where favorite.Get<string>("user") == ParseUser.CurrentUser.Username
select favorite;
IEnumerable<ParseObject> results = await query.FindAsync();
I had a similar Problem.All u want to do here is generate a new instance of the Page.U can do this in two Ways.
One Way is by forcing a GUID along with Page Navigation URI that will create a New Instance of the Page and your Load Data() will work.
NavigationService.Navigate(new Uri(String.Format("/MainPage.xaml?item={0}", Guid.NewGuid().ToString()), UriKind.RelativeOrAbsolute));
The Second Way to implement that Part of your Page in a User Control .Like create a User Control for Load Data() and put it in constructor.It will generate a new Instance everytime you load the Page.
If the problem persists in the front end,you can try this.
1.have you mentioned the below attribute in your xaml page?
<UserControl Loaded="MainPage_Loaded">
So that every time the page loads the data will get loaded on to the page.
2.The data must exist, if you have no problem in the code behind as it is a WPF application and not a web page.
Hope you find it useful.
Two changes required..
Remove the this.Loaded from OnNavigatedTo. That may not be required.
Second move the LoadData to OnNavigatedTo method
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
App.PersonalizedViewModel.favorites.Clear();
DataContext = App.PersonalizedViewModel;
// this.Loaded += new RoutedEventHandler(MainPage_Loaded);
if (!App.PersonalizedViewModel.IsDataLoaded)
{
App.PersonalizedViewModel.LoadData();
}
}
For the purpose of debugging, you can remove the line if (!App.PersonalizedViewModel.IsDataLoaded) and try.

Universal Hub App sample does not return right number of items when trimmed

I’m trying to edit the Windows Store Universal Hub App sample in VS 2013. There is a SampleDataSource.cs that takes in data from a SampleData.json, and presents it when asked for. The method I’m interested in is SampleDataSource.GetGroupAsync. Assuming I have 10 items in a group (in the json file), I’d like to display only 6 on the landing page (HubPage), and all 10 on the SectionPage (the page you get when you click on the Hub Section header).
So I modified the code to do this.
HubPage.xaml.cs
private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
// TODO: Create an appropriate data model for your problem domain to replace the sample data
var sampleDataGroup = await SampleDataSource.GetGroupAsync("Group-4");
// Trim items to top 6 only
if (sampleDataGroup.Items.Count > 6)
{
for (int removeIndex = sampleDataGroup.Items.Count - 1; sampleDataGroup.Items.Count > 6; removeIndex--)
{
sampleDataGroup.Items.RemoveAt(removeIndex);
}
}
this.DefaultViewModel["Section3Items"] = sampleDataGroup;
}
However, when I navigate to SectionPage, I only see 6 items, instead of all 10. Why does this happen? I am calling SampleDataSource.GetGroupAsync again, the original collection or the json file was not modified by my trimming down to 6 items, so why am I receiving only 6 from SampleDataSource? I have confirmed that this is indeed “Group-4”
SectionPage.xaml.cs
private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
// TODO: Create an appropriate data model for your problem domain to replace the sample data
var group = await SampleDataSource.GetGroupAsync((string)e.NavigationParameter);
this.DefaultViewModel["Group"] = group;
this.DefaultViewModel["Items"] = group.Items;
}
Here is a direct link to the samples. I'm using the C# version:
http://code.msdn.microsoft.com/wpapps/Universal-Windows-app-cb3248c3

Trying to make method wait for internal event handling finished

I'm new in C# async/await and facing some issues while trying to work with async method.
I have a collection:
private IList<IContactInfo> _contactInfoList
And an async method:
public async Task<IList<IContactInfo>> SelectContacts()
{
_contactInfoList = new List<IContactInfo>();
ContactsSelector selector = new ContactsSelector();
selector.ShowPicker();
selector.ContactsSelected += (object sender, ContactsSelectorEventArgs e) =>
{
this._contactInfoList = e.Contacts;
};
return _contactInfoList;
}
Contact selector is a popup user control which allows to select some contacts from phone and after the "OK" button tapped it fires ContactsSelected event. I need to get the selected contacts list from the event arguments e.Contacts and return that list in above mentioned SelectContacts() async method. And here is the issue: My method is already returning empty list _contactInfoList before the ContactsSelected event has finished his job. I know that async/await even doesn't matter in this case and this issue will be exist in usual method, but I just need to make that method to wait event handling result.
What you need to do here is convert an event style of asynchronous programming to a task style of asynchronous programming. The use of a TaskCompletionSource make this fairly straightforward.
public static Task<IList<IContactInfo>> WhenContactsSelected(
this ContactsSelector selector)
{
var tcs = new TaskCompletionSource<IList<IContactInfo>>();
selector.ContactsSelected += (object sender, ContactsSelectorEventArgs e) =>
{
tcs.TrySetResult(e.Contacts);
};
return tcs.Task;
}
Now that we have a method that returns a task with the result that we need, the method that uses it is quite straightforward:
public Task<IList<IContactInfo>> SelectContacts()
{
ContactsSelector selector = new ContactsSelector();
selector.ShowPicker();
return selector.WhenContactsSelected();
}
There are a few things to note here. First, I removed the instance field; that seems like a bad idea here. If SelectContacts is called several times it would result in the two fighting over that field. Logically if you do need to store the list it should be a local variable. Next, there are no await uses here, so the method shouldn't be marked as async. If you wanted to await the call to WhenContactsSelected then feel free to add async back in, but as of now I see no real need for it.

Basic use of user controls, closing a user control and opening another, user control parameters

ladies and gentlemen, once again I unfortunately am going to bother you with newbie stuff. I have searched for this information for hours, so if there’s a thread with what I want on it, it’s buried deeper than I could find.
This was my first question here, and Mark Hall was kind enough to set me straight. Since then, I have created a new project and recreated my first three screens as user controls – a container/login, a choice screen, and a main screen (currently empty). If a user has more than one collection, the choice screen pops up and allows them to choose a collection.
I did run into a snag with parameters, but I’m solving that by overloading the form declaration (solution found here) – yes, I know it’s much better to send parameters through calls, but I’d hate to have to create a call for each parameter (do I?) and… OK, OK, I’m better at this than {get, set}. Man, I hate being a newbie.
Anyways, I’m having trouble with the choice form – I can’t seem to call it, close it, then go to the main form. I have no problem (if there’s only one collection) in going straight to the main form, it’s that darn choice form. Yes, I know I could include a choice datagridview, but a few of our end users aren’t the sharpest bulb in the tool shed, and need hand-holding. Anyways, here’s the code.
CONTAINER/LOGIN SCREEN
namespace DeleteThis
{
public partial class ContainerForm : Form
{
Main Main = new Main();
LoginCollectionChoice LoginChoice = new LoginCollectionChoice();
DataTable dtPermissions = new DataTable();
public ContainerForm()
{
InitializeComponent();
Main.ExitEvent += new Main.ExitEventHandler(Main_ExitEvent);
LoginChoice.ExitEvent += new
LoginCollectionChoice.ExitEventHandler(LoginChoice_ExitEvent);
}
void LoginChoice_ExitEvent(object sender, EventArgs e)
{
pnlcontainer.Controls.Remove(LoginChoice);
}
void Main_ExitEvent(object sender, EventArgs e)
{
pnlcontainer.Controls.Remove(Main);
}
private void btnLogin_Click(object sender, EventArgs e)
{
LoginProcedure();
}
private void LoginProcedure()
{
DataTable dtPermissions = AdminClass.GetCollectionsForUser(int.Parse(txtbxUserName.Text));
if (dtPermissions.Rows.Count == 1)
{
//Valid user, one collection. Head right in.
pnlcontainer.Controls.Add(Main);
Main.BringToFront();
}
else
{
//More than one collection found. Giving user choice
LoginCollectionChoice LoginChoice = new LoginCollectionChoice(dtPermissions);
pnlcontainer.Controls.Add(LoginChoice);
LoginChoice.BringToFront();
}
}
private void btnExitProgram_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
I hope I didn't kill anything in the snipping. And now the choice screen…
public partial class LoginCollectionChoice : UserControl
{
public delegate void ExitEventHandler(object sender, EventArgs e);
public event ExitEventHandler ExitEvent;
private static DataTable dtPermit;
DataTable dtPermissions = new DataTable();
public LoginCollectionChoice()
{
}
public LoginCollectionChoice(DataTable dtPermissions)
{
InitializeComponent();
GrdCollection.DataSource = dtPermissions;
dtPermit = dtPermissions;
}
private void btnChoose_Click(object sender, EventArgs e)
{
//Code for the user to choose a collection
ExitEvent(this, new EventArgs());
}
}
I’ve snipped all non-relevent code, I hope you gentlemen and ladies can help this newbie get on the right path. Please, be gentle, you wouldn’t want to see me cry, would you? :) Oh! And if you know of any great tutorial sites, please email them to me. I'd prefer to spend a week on tutorials than a week on stumbling and asking here. Thank you all very much.
Are you calling logonForm.Show()?
It seems like you'd need to show it that way.
You use BringToFront(), but I think it needs to be shown first.
The first thing that jumps out to me is that you are calling
LoginCollectionChoice LoginChoice = new LoginCollectionChoice(dtPermissions);
which is creating a local variable called LoginChoice, which is not the same as your class variable even though they share the same name.
What you want to do is to not declare a local variable in that method. Change that line to
LoginChoice = new LoginCollectionChoice(dtPermissions);
Having said that, I believe tylerjgarland in that you need to call .Show() first. And the way you are closing the form is certainly odd. I would create a form, showDialog, get the result and then close the form that way.

Categories