I need some help with passing the ListView Tapped Id (which I get from a json).
I populate the listView with an API call to a server:
private async void searchButton_Click(object sender, RoutedEventArgs e)
{
var textFrom = odTextBox.Text;
var textTo = doTextBox.Text;
var searchResult = await PrevoziApi.SearchRidesAsync(textFrom, textTo, datePicker.Date.UtcDateTime);
var array = searchResult.CarshareList
.OrderBy(cs => cs.Time)
.Select(cs => cs.Contact + " " + cs.Time)
.ToArray();
listView.ItemsSource = array;
}
Now, when I click on an item of listView, I want to navigate to another page(CarShareDetailedPage) and make another call to the API, to get more detailed data about that item. So I need to pass the selectedItem id from one page to other. How do I do that ?
I'm navigating to another page like this:
private void listView_Tapped(object sender, TappedRoutedEventArgs e)
{
Frame.Navigate(typeof(CarShareDetailedPage), listView.SelectedIndex);
}
The OnNagiatedMethod on that page is:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var value = e.ToString();
carShareTextBox.Text = value;
}
And my json class is:
public class CarshareList
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("from_id")]
public string FromId { get; set; }
[JsonProperty("from_country")]
public string FromCountry { get; set; }
[JsonProperty("from_country_name")]
public string FromCountryName { get; set; }
[JsonProperty("to_id")]
public string ToId { get; set; }
[JsonProperty("to")]
public string To { get; set; }
[JsonProperty("to_country")]
public string ToCountry { get; set; }
[JsonProperty("to_country_name")]
public string ToCountryName { get; set; }
[JsonProperty("time")]
public string Time { get; set; }
[JsonProperty("date_iso8601")]
public DateTime DateIso8601 { get; set; }
[JsonProperty("added")]
public DateTime Added { get; set; }
[JsonProperty("price")]
public double? Price { get; set; }
[JsonProperty("num_people")]
public double NumPeople { get; set; }
[JsonProperty("author")]
public string Author { get; set; }
[JsonProperty("is_author")]
public string IsAuthor { get; set; }
[JsonProperty("comment")]
public string Comment { get; set; }
[JsonProperty("contact")]
public string Contact { get; set; }
[JsonProperty("date")]
public string Date { get; set; }
[JsonProperty("full")]
public string Full { get; set; }
[JsonProperty("insured")]
public string Insured { get; set; }
[JsonProperty("share_type")]
public string ShareType { get; set; }
[JsonProperty("confirmed_contact")]
public string ConfirmedContact { get; set; }
[JsonProperty("bookmark")]
public object Bookmark { get; set; }
[JsonProperty("from")]
public string From { get; set; }
}
public class CarshareResponse
{
[JsonProperty("search_type")]
public string SearchType { get; set; }
[JsonProperty("carshare_list")]
public IList<CarshareList> CarshareList { get; set; }
}
Let me say this is the first time ever I'm doing any work with Apis and json.
Thanks for your help!
EDIT: I added the code for the API below, so this now should be all the code I have.
public class PrevoziApi
{ public static async Task<CarshareResponse> SearchRidesAsync(
string fromCity,
string toCity,
DateTime date,
string type = "shares",
CancellationToken token = default(CancellationToken))
{
using (var client = new RestClient("https://prevoz.org/api/"))
{
var request = new RestRequest("search/" + type + "/", HttpMethod.Get);
request.AddQueryParameter("f", fromCity);
request.AddQueryParameter("fc", "SI");
request.AddQueryParameter("t", toCity);
request.AddQueryParameter("tc", "SI");
request.AddQueryParameter("d", date.ToString("yyyy-MM-dd"));
request.AddQueryParameter("exact", "true");
return
(await client.Execute<CarshareResponse>(request, token)).Data;
}
}
}
So with this, you are ordering by the time but displaying a string only that says "[Contact] [Time]". This in-and-of-itself does not hold any relation to the JSON that was returned from your search method. What you'll want to do is instead of making it an array, instead making a List<> object that can store some additional "background" data about that request to send off.
This will require a bit more effort though on your end. You will want to create a class
public class CarItemView {
public string DisplayText {get; set;}
public int ID {get; set;}
}
and fill it with whatever data you want to pass along. Then in your filtering you would do:
List<CarItemView> array = searchResult.CarshareList
.OrderBy(cs => cs.Time)
.Select(cs => new { DisplayText = cs.Contact + " " + cs.Time, ID = cs.Id}).ToList();
You will then, in your XAML, have to add a template to your listview for display. (Note, this is a real rough outline for a XAML Template)
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding DisplayText}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
NOW when you get your selected item changed event fired, you can handle it and get the ID.
private void listView_Tapped(object sender, TappedRoutedEventArgs e)
{
var obj = (CarItemView) listView.SelectedItem; // convert item to our new class
Frame.Navigate(typeof(CarShareDetailedPage), obj.Id.ToString()); // send ID as string
}
Then for the receiving page:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var value = e.ToString();
carShareTextBox.Text = value; // will show the ID number
var caritemret = /* write a new restful function to return based on ID */
}
UPDATE: This answer was updated from original to reflect the use of an array instead of a list<> object
I hope this helps!
This works:
private async void searchButton_Click(object sender, RoutedEventArgs e)
{
var textFrom = odTextBox.Text;
var textTo = doTextBox.Text;
var searchResult = await PrevoziApi.SearchRidesAsync(textFrom, textTo, datePicker.Date.UtcDateTime);
List<CarItemView> array = searchResult.CarshareList
.OrderBy(cs => cs.Time)
.Select(cs => new CarItemView { DisplayText = cs.Contact + " " + cs.Time, Id = cs.Id })
.ToList();
listView.ItemsSource = array;
}
private void listView_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
var obj = (CarItemView)listView.SelectedItem; // convert item to our new class
Frame.Navigate(typeof(CarShareDetailedPage), obj.Id); // send ID as string
}
And on navigated to method on the destination page:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var value = e.Parameter.ToString();
carShareTextBox.Text = value; // will show the ID number
/* write a new restful function to return based on ID */
}
Thanks #daniel, it was mostly as you suggested, with a few errors, but with the help of some guys at the c# chat channel I managed. Thanks to all.
Related
I have an ObservableCollection<DiscoveredScooter> DiscoveredScooters = new ObservableCollection<DiscoveredScooter>. The DiscoveredScooter class looks like this:
public class DiscoveredScooter : ViewModel
{
public string Id { get; set; }
public string Name { get; set; }
public string Model { get; set; }
public int RSSI { get; set; }
public DiscoveredScooter(string id, string name, string model, int rssi)
{
Id = id;
Name = name;
Model = model;
RSSI = rssi;
}
public void Update(DeviceInformationUpdate d, string model, int rssi)
{
Id = d.Id;
RSSI = rssi;
Model = model;
RaisePropertyChanged(nameof(Id));
RaisePropertyChanged(nameof(RSSI));
RaisePropertyChanged(nameof(Model));
}
public void UpdateRSSI(int rssi)
{
RSSI = rssi;
RaisePropertyChanged(nameof(RSSI));
}
}
My XAML has a Listview which is bound to this ObservableCollection. I have a BluetoothAdvertismentEvent that gets fired whenever I receive advertisement data. I do some validation and then I do
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
DiscoveredScooters.Add(new DiscoveredScooter(args.BluetoothAddress.ToString(), bleDeviceName, beaconParser.HumanReadableModel, (int)args.RawSignalStrengthInDBm));
});
But this causes a "XAML generated UnhandledException" and it doesn't say any more about the error whatsoever. Here is a screenshot https://gyazo.com/42ee2cae9018c05087335f77db83cb99 Any help is appreciated.
The issue was that I was using .Substring(41) on a property, where the length was way less than that.
I am trying to add the content of my BindingList into a txt file. However, I always get the following error:
System.NullReferenceException: Object reference not set to an instance of an object.
What am I doing wrong? The text file is empty if that helps.
Code:
BindingList<Student> StudentCollection = new BindingList<Student>();
private void btnAddStudent_Click(object sender, EventArgs e)
{
Student StudentSave = new Student
{
ID = txtStudentID.Text,
FirstName = txtFirstName.Text,
LastName = txtLastName.Text,
Age = nudAge.Value,
Height = nudHeight.Value,
Schoolclass = txtSchoolClass.Text,
Gender = cbxGender.Text,
};
cbxStudentIDs.DataSource = StudentCollection;
cbxStudentIDs.DisplayMember = "ID";
StudentCollection.Add(StudentSave);
}
public class Student
{
public string ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public decimal Age { get; set; }
public decimal Height { get; set; }
public string Schoolclass { get; set; }
public string Gender { get; set; }
}
private void Form1_Load(object sender, EventArgs e)
{
string studentCollectionString = File.ReadAllText(FilePath);
StudentCollection = JsonConvert.DeserializeObject<BindingList<Student>>(studentCollectionString);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
string studentCollectionString = JsonConvert.SerializeObject(StudentCollection);
File.WriteAllText(FilePath, studentCollectionString);
}
Issue
This is where you will get the exception, as you mentioned text file is empty and StudentCollection will be set to null
StudentCollection = JsonConvert.DeserializeObject<BindingList<Student>>(studentCollectionString);
Solution
You should change the code like this: the ? will ensure that operation proceeds only if you have valid result in the text file.
JsonConvert.DeserializeObject<BindingList<Student>>(studentCollectionString)?.ToList().ForEach(a => StudentCollection.Add(a));
Ensure your Filepath does exist if not exist you should create the file then write to file, also ensure that your json is not empty
https://learn.microsoft.com/en-us/dotnet/api/system.io.file.create?view=netcore-3.1
This is my code:
But I will Add the values (see code) if someone clicked the Button "Einfügen".
But it doesn't work, It only change his values!
Thanks for all helpers!
private void Einfügen_Click(object sender, RoutedEventArgs e)
{
var itemsEnd = new List<Plan>();
itemsEnd.Add(new Plan(LinieZ, Convert.ToString(Kurs.SelectedItem), AbfZ, VonZ, NachZ, AnkZ, "---"));
Plan.ItemsSource = itemsEnd;
}
class Plan
{
public string Linie { get; set; }
public string Kurs { get; set; }
public string Abfahrt { get; set; }
public string Von { get; set; }
public string Nach { get; set; }
public string Ankunft { get; set; }
public string Pause { get; set; }
public Plan(string Linie, string Kurs, string Abfahrt, string Von, string Nach, string Ankunft, string Pause)
{
this.Linie = Linie;
this.Kurs = Kurs;
this.Abfahrt = Abfahrt;
this.Von = Von;
this.Nach = Nach;
this.Ankunft = Ankunft;
this.Pause = Pause;
}
}
The problem is that you are resetting the ItemsSource each time to a brand new List (of size 1). You are not appending to the List, but instead, you are creating a List that only has the new item, then setting that List to the DataGrid.
You can have a predefined list that you add to.
Something like:
private ObservableCollection<Plan> _items = new ObservableCollection<Plan>();
public Window()
{
InitializeComponent();
Plan.ItemsSource = _items;
}
private void Einfügen_Click(object sender, RoutedEventArgs e)
{
_items.Add(new Plan(LinieZ, Convert.ToString(Kurs.SelectedItem), AbfZ, VonZ, NachZ, AnkZ, "---"));
}
Though, I would suggest not going this route. Look into MVVM, DataBinding, and Commands. Ideally, you would want to create a ViewModel that contains an ObservableCollection that is bound to the DataGrid. Inside that ViewModel will be a command that will add items to that ObservableCollection.
I created a Windows phone 8.1 application with a listview on Startpage.xaml. When I update listview values, I don't see the changes on the phone until I close and open the application again. I tried to update the listview when I clicked the refresh button, but unsuccessfully. Anyone know how to update a listview when I click the refresh button?
How I fill in data in the listview:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedTo(e);
HttpClient http = new HttpClient();
string str = ((ComboBoxItem)cbox.SelectedItem).Content.ToString();
var response = await http.GetStringAsync("http://mywebpage.si/events/apis/facebook_events.php?city=" + str + "&user=" + uporabnik.user);
var FSfeed = JsonConvert.DeserializeObject<List<Class1>>(response);
Reviews.ItemsSource = FSfeed;
}
My class:
public class Class1
{
public string title { get; set; }
public string description { get; set; }
public string image { get; set; }
public string start { get; set; }
public string end { get; set; }
public string location { get; set; }
public string city { get; set; }
public int id { get; set; }
}
Refresh button:
private async void refresh_Click(object sender, RoutedEventArgs e)
{
HttpClient http = new HttpClient();
string str = ((ComboBoxItem)cbox.SelectedItem).Content.ToString();
var response = await http.GetStringAsync("http://mywebpage.si/events/apis/facebook_events.php?city=" + str + "&user=" + uporabnik.user);
var FSfeed = JsonConvert.DeserializeObject<List<Class1>>(response);
Reviews.ItemsSource = FSfeed;
}
I also tried to refresh like this, but unsuccessfully:
private async void refresh_Click(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(PivotPage));
}
To update the view you need to update the binding to ItemSource:
List<Class1> mySource = new List<Class1>();
Binding binding = new Binding { Source = mySource };
BindingOperations.SetBinding(myListView, Windows.UI.Xaml.Controls.ListView.ItemsSourceProperty, binding);
I use .net framework 4, and petapoco to create a my first Web API module in dnn. here is my code:
[TableName("TblBPMProcess")]
[PrimaryKey("ProcessID", AutoIncrement = true)]
[Cacheable("ProcessInfo", CacheItemPriority.Default, 20)]
[Scope("ModuleId")]
public class ProcessInfo
{
public int ProcessID { get; set; }
public int ModuleID { get; set; }
public string DynamicModuleID { get; set; }
public string ProcessCaption { get; set; }
public int Availability { get; set; }
public int CreatedBy { get; set; }
public string CreatedDate { get; set; }
public string ModifiedDate { get; set; }
}
In controller:
public IEnumerable<ProcessInfo> GetList(int ModuleID)
{
IEnumerable<ProcessInfo> item;
using (IDataContext ctx = DataContext.Instance())
{
var rep = ctx.GetRepository<ProcessInfo>();
item = rep.Get(ModuleID);
}
return item;
}
In codebehind:
protected void Page_Load(object sender, EventArgs e)
{
var cnt = new StateController();
IEnumerable<StateInfo> lst = cnt.GetList(1);
rptHostList.DataSource = lst;
}
in Page_Load, lst returns null. i double checked all columns and table names. there is neither error nor data. Any Idea?
As I understand the method may return an IEnumerable with items or null (if there is no items).
So all what you need to do is check if the returned value is not null:
protected void Page_Load(object sender, EventArgs e)
{
var cnt = new StateController();
IEnumerable<StateInfo> lst = cnt.GetList(1);
if (lst != null)
{
rptHostList.DataSource = lst;
}
}
In [Scope("ModuleId")] , I believe that puts in the current ModuleId instead of the one you are passing in.
You may want to comment that out or change it, and see if it works. It may be getting it confused some how.