Navigate to page based on itemview clicked item - c#

i have a simple list that is bound to a gridview control, upon the itemview's click event i'd like to navigate to the page.
My class looks like;
public class GetMenu
{
public string titleName { get; set; }
public string imagePath { get; set; }
public string pagePath { get; set; }
}
An example of the data with the list;
new GetMenu(){titleName = "Services", imagePath = "Bouquets.xaml", pagePath="Services.xaml"}
For the click even have the following;
void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
}
I believe i need to extract the click event data from e, i'm a little unsure on how to do this.

If I understand your question correctly, i.e you want to get 'clicked' item, then it should be fairly easy:
var getMenu = (GetMenu)e.ClickedItem;
Now you have the item and you can use the properties inside as navigation parameters.
Is that what you had in mind?
[EDIT]
The navigation itself is fairly simple, too. If you're in code-behind, you have to:
Frame.Navigate(typeof(YourViewForTheItem), parameters);
e.g.
Frame.Navigate(typeof(ItemDetailsView), getMenu);
parameters is an object, so you will have to cast it appropriately in OnNavigatedTo in the target view.
If you're using any kind of MVVM framework, there are services for that too, e.g. Caliburn.Micro has INavigationService.
That's of course if you know the type beforehand.
If you want to create the 'type' itself from a string you have, you will have to use reflection:
var viewType = Type.GetType("YourStoreApp.Views."+getMenu.pagePath.Substring(0, getMenu.pagePath.LastIndexOf("."));
Assuming the pagePath is not null.
The type string has to be fully qualified name, that is full assembly name and type (without extension), so e.g "YourStoreApp.Views.Services". The file name has to mirror the type name exactly for this to work though.
Now you can:
Frame.Navigate(viewType);

Related

MVVMCross add multiple dynamic properties to viewmodel

I have an requirement to render the screen (screen type : form) dynamically based on the service response (rather than defining the UI manually). I was able to successfully bind predefined properties to dynamically created textboxes & textviews. Following is the sample code that used to bind predefined property to dynamic textbox
Type myType = typeof(DynamicViewModel);
PropertyInfo myPropInfo = myType.GetProperty(nameof(dynamicProperty)); //dynamicProperty -static property in VM
var set = this.CreateBindingSet<DynamicActivity, DynamicViewModel>();
set.Bind(editText).To(myPropInfo.Name); //editText - dynamically created textbox
set.Apply();
But the code needs to be further improved by dynamically creating the no of properties - matching with the no of UI elements dynamically created.
The project is created using Xamarin.Android with MVVMCross's latest version. Please share the way to generate dynamic string(or object type) properties in viewmodels that can be binded with dynamically generated view elements(textboxes & textviews).
Thanks
There are a couple of ways to do this.
One is using Reflection as you are doing there, but you could have performance issues.
The other way is to arrange a bit the data and model you are getting from the server to be something like you can then use some Factories to build your View/VM:
So it could be:
public enum DataType
{
String,
Number,
Boolean,
List,
// and any other types that you need
}
public class OptionItemModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public class FieldModel
{
public DataType Type { get; set; }
public string DefaultValue { get; set; } // this is a serialized value
public List<OptionItemModel> Options { get; set; } // this only applies to DataType -> List
}
public class StructureModel
{
public List<FieldModel> Fields { get; set; }
}
So then you can have an ObservableCollection on your VM and your items can be created by a factory iterating for each one of the fields of the structure and so you can have custom Item View Models depending on the DataType of the field.
Then you can have a List on your View that uses a Template selector where you can create the Cell/Row depending on the DataType or the ItemViewModel and that would be it.
Then you can have a similar model structure to fill the values and upload them to the server.
Hope it's clear enough

c# How to call existing item of form having its name stored in new string?

I have multiple datagrids and i would like to move data from one to another.
The problem is:
I have their names "made" into string variables:
string gridfrom = "datagrid" + cplist1.SelectedItem.ToString();
string gridto = "datagrid" + cplist2.SelectedItem.ToString();
In this case, i know that gridfrom = datagridMAR and gridto = datagridAPR
But gridfrom and gridto changes according to the listboxes selected items.
How do i call these objects (already existing in the form) to change its properties? For example:
gridto.DataSource = gridfrom;
Thanks in advance
Let me tell you an elegant way of dealing with this situation without getting into dynamic type loading, etc
Create a custom type, say
class GridName {
public DataGridView Grid {get; private set;}
public string Name {get; private set;}
public GridName(DatagridView grid, string name) {
Grid = grid;
Name = name;
}
public string override ToString() {
return Name;
}
}
Now, instead of adding a string into the cplist1 and cplist2, simply add GridName object into it. It will display the name correctly and also when you want the grid associated with it, you can access the .Grid property
There are many other ways of doing it. For example, you can use ValueMember and DisplayMember property.
I would definitely resist against trying to convert the grid name into a DatagridView object.

How to add items to a list in C# using a class containing public variables

I hope you can help out a fellow programmer. Basically, I want the user input from the Rich Text Box (taskNameRTB) to be assigned to the taskName; string variable in my class taskStructure which is in form1 shown below:
public partial class Form1 : Form
{
public class taskStructure
{
public string taskName;
public string taskDescription;
public int Priority;
public string dateAndTime;
}
public List<taskStructure> TasksArray = new List<taskStructure>(); //Declared a list data structure
In my second form which is where the user enters everything related to the task, I want to send this information to the list after the 'Create Task' button has been clicked:
private void createTaskBtn_Click(object sender, EventArgs e)
{
Form1 welcomeForm = new Form1();
welcomeForm.TasksArray[0].taskName = taskNameRTB.Text;
welcomeForm.TasksArray[0].taskDescription = taskDescRTB.Text;
}
However, when I do this I get a ArgumentOutOfRangeException and I do not understand why. I have also tried these:
welcomeForm.TasksArray[0].Add(taskDescRTB.Text);
welcomeForm.TasksArray.Insert(0, taskNameRTB.Text);
welcomeForm.TasksArray.Add(taskDescRTB.Text);
taskNameRTB.Text = welcomeForm.TasksArray[0].taskName;
But the ones that run come up with the same error ArgumentOutOfRangeException and some of them don't work, such as:
welcomeForm.TasksArray[0].Add(taskDescRTB.Text);
I'm aware that the list has not been initialized, but how can I initialize it when it doesn't allow me to initialize it with user input...
Any light you can shed on this will be really helpful
Kind Regards,
Kieran
You need to add a new taskStructrue to the list.
welcomeForm.TasksArray.Add(new taskStructure
{
taskName = taskDescRTB.Text,
taskDescription = taskDescRTB.Text
});
But personally I'd rewrite that class to follow naming conventions and to use properties instead of public fields.
public class TaskStructure
{
public string TaskName { get; set; }
public string TaskDescription { get; set; }
public int Priority { get; set; }
public string DateAndTime { get; set; }
}
have you tried
welcomeForm.TasksArray.Add(new taskStructure(taskDescRTB.Text));
I don't know what taskStructure is, but you need to fill TasksArray with types of it.
Your TaskStructure is a class, and you are putting all TaskStructure objects into a list,
public List<taskStructure> TasksArray = new List<taskStructure>(); //Declared a list data structure
Does your Form1() have a constructor that calls InitializeComponents()?
If so, you could try adding TasksArray = new List<taskStructure>() right below InitializeComponents(), because it looks like you're trying to access the list data structure that hasn't been initialized with new.
Alternatively
As another user noted, you can create a constructor class for TaskStructure like this:
public TaskStructure(RTB rtb1, rtb2, rtb3) //where RTB is the rich text box type
{
taskName = rtb1.text;
taskDescription = rtb2.text;
//and so on.
}
Then you can do TaskArray.add(new TaskStruture(rtb1,rtb2,rtb3).
Thrid Edit
Just realized your TaskArray is actually a List, which in C# (and Java), you cannot access it with an index like TaskArray[0], you have to use getter and setter methods, which in this case is TaskArray.add(), and TaskArray.get(0), you're getting ArgumentOutOfRangeException because you're trying to access a List using square indexes like this --> [0]. You can actually access a list doing list1, as pointed out by another user.
Here's a good tutorial on C# lists, by DotNetPerls

Generated a list of filenames, but no file paths

I have a list box that displays a set of filenames that reference text files. I think it is aesthetically unappealing to display full paths, so I used Path.GetFileName to cut off the directory part.
But now when the user selects a particular filename to open, I've lost the paths. The files could be located anywhere on the local computer (for now).
How can I use the list box so that I can display nice filenames, but also have reference to the actual file?
EDIT: I like the idea of having a custom wrapper class for each list box item.
What's I've done in the past is create a wrapper class for the objects I want to display in the ListBox. In this class override ToString to the string you want to display in the ListBox.
When you need to get details of a selected item, cast it to the wrapper class and pull the data you need.
Here's an ugly example:
class FileListBoxItem
{
public string FileFullname { get; set; }
public override string ToString() {
return Path.GetFileName(FileFullname);
}
}
Fill your ListBox with FileListBoxItems:
listBox1.Items.Add(new FileListBoxItem { FileFullname = #"c:\TestFolder\file1.txt" })
Get back the full name of a selected file like this:
var fileFullname = ((FileListBoxItem)listBox1.SelectedItem).FileFullname;
Edit
#user1154664 raises a good point in a comment to your original question: how would a user differentiate two ListBox items if the displayed file names are the same?
Here are two options:
Also display each FileListBoxItem's parent directory
To do this change the ToString override to this:
public override string ToString() {
var di = new DirectoryInfo(FileFullname);
return string.Format(#"...\{0}\{1}", di.Parent.Name, di.Name);
}
Display a FileListBoxItem's full path in a tooltip
To do this drop a ToolTip component on your form and add a MouseMove event handler for your ListBox to retrieve the FileFullname property value of the FileLIstBoxItem the user is hovering the mouse over.
private void listBox1_MouseMove(object sender, MouseEventArgs e) {
string caption = "";
int index = listBox1.IndexFromPoint(e.Location);
if ((index >= 0) && (index < listBox1.Items.Count)) {
caption = ((FileListBoxItem)listBox1.Items[index]).FileFullname;
}
toolTip1.SetToolTip(listBox1, caption);
}
Of course you can use this second option with the first.
Source for the ToolTip in a ListBox (the accepted answer, code reformatted to a flavor I prefer).
Use ListBoxItem.Tag to store the full path for each item if using WPF. Or, if using WinForms, you can create a custom class that stores the full path, but overrides object.ToString() so that only the filename is displayed.
class MyPathItem
{
public string Path { get; set; }
public override string ToString()
{
return System.IO.Path.GetFileName(Path);
}
}
...
foreach (var fullPath in GetFullPaths())
{
myListBox.Add(new MyPathItem { Path = fullPath });
}
I do this
public class ListOption
{
public ListOption(string text, string value)
{
Value = value;
Text = text;
}
public string Value { get; set; }
public string Text { get; set; }
}
Then create my list
List<ListOption> options = new List<ListOption>()
For each item in files
options.Add(new ListOption(item.Name, item.Value));
Next
bind my list
myListBox.ItemSource = options;
Then get my value or text
protected void List_SelectionChanged(...)
{
ListOption option = (ListOption) myListBox.SelectedItem;
doSomethingWith(option.Value);
}
Just the idea here is main thing
Personally I don't agree with you sentiment that this is ugly for the user. Showing the full path gives the explicit details to the user and enable them to have confidence in their selection or what ever they are doing.
I would use a Dictionary, using the item index as the Key and the full path of this list item as the value.
Dictionary<int, string> pathDict = new Dictionary<int, string>();
pathDict.Add(0, "C:\SomePath\SomeFileName.txt");
...
The above is probably the best way to go here over using the item.Tag property...
I hope this helps.

Passing c# ListBox Item to method

Small programming problem here, hopefully someone can point me in the right direction.
Im using a list here on a WP7 page. (Silverlight ListBox).
My list is populated by an XML file. Each List item has three text boxes populated as per the code below.
I need to pass one of the selected ListBox items as text to the following method to poulate the phone number.
This is my c# code which populates the listbox, and then the phonecall method.
private void planning(object sender, ManipulationStartedEventArgs e)
{
XElement _xml = XElement.Load("contacts/contacts.xml");
{
contacts.Items.Clear();
foreach (XElement value in _xml.Elements("channel").Elements("item"))
{
ContactsItem _item = new ContactsItem();
_item.Title = value.Element("title").Value;
_item.Web = value.Element("web").Value;
_item.Phone = value.Element("phone").Value;
contacts.Items.Add(_item);
}
}
}
private void phone_number(object sender, MouseButtonEventArgs e)
{
Microsoft.Phone.Tasks.PhoneCallTask phonecall = new Microsoft.Phone.Tasks.PhoneCallTask();
phonecall.PhoneNumber = //value here
phonecall.Show();
}
With my accompanying class:
public class ContactsItem
{
private string _title;
private string _web;
private string _phone;
public string Title
{
get { return _title; }
set { _title = value; }
}
//etc etc....
The idea is, when you click on the binded 'Phone' text in the list box, it will pass that value to the phonecall method. When the text box with the phone number is clicked, it calls that phone_number method.
Hope you understand. Many thanks.
Look into the sender's DataContext property (you may have to do some type casting) in the phonecall method (I mean the handler which handles the ListBoxItem's click event). If the ListBox is bound correctly, the ContactsItem will be the menu item's DataContext.
Also, as a side note: Learn to follow .NET's naming standards (CamelCase for methods), it will make your life much easier in the long run, especially if you were to collaborate with other propgrammers.
And you can use this to generate simple properties with basic getters/setters:
public string Name {get; private set;}
Assuming "contacts" is your ListBox, you could get the phone number by doing
((ContactsItem)contacts.SelectedItem).Phone

Categories