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
Related
So Im trying to creat a simple app like a shopping app. so I have categories and multiple items for each category, and when you get to choose an item then you will have the posibility to increase how many you need or delete the item. For exemple I chosed three items, so my cart have 3 items where each one have an Add button and a delete button. When I hit the add button the number of the items shown should increase and so on.
so what I've done so far is creating a JSON file that having all my categories, and once I hit a category I get to deserialize another JSON file that have all my items, so the items shown depends on the category I chosed of course.
Now each time i choose an item it get added to the cart and shown on the bottom page with a + and - buttons and so on.
so I created a category class to deserialize my json, and an objets class to deserialize my Item's json. I implememted the INotifyChangedProperty in the objets class so that I can keep showin whenever the number of a chosen item get increased, so basicly thats my ViewModel, but I guess that it's like that I need a ViewModel of each created item ? so I guess what I really need to use is the ObservableCollection ..
I hope I explained everything well, and waiting for your feedbacks about if Im doing it right or wrong and how should i proceed to get what I want. thank you so much
the problems is that to set the bindingcontext to my "Objets" Class I have to put the arguments in it, and then my Label well get a precised value ... what should I do ?
I do one sample about your model, you can take a look:
<ContentPage.Content>
<StackLayout>
<Label x:Name="label1" />
<Button
x:Name="btn1"
Clicked="Btn1_Clicked"
Text="change value" />
</StackLayout>
</ContentPage.Content>
public partial class Page15 : ContentPage
{
public Objets model { get; set; }
public Page15()
{
InitializeComponent();
model= new Objets("test 1", 1.001f, " test11111", 12);
this.BindingContext = model;
label1.SetBinding(Label.TextProperty, "nbr_objet");
}
private void Btn1_Clicked(object sender, EventArgs e)
{
model.nbr_objet = 20;
}
}
public class Objets : INotifyPropertyChanged
{
public string Designation { get; set; }
public float Prix { get; set; }
public string imageUrl { get; set; }
private int Nbr_Objet;
public int nbr_objet
{
get { return Nbr_Objet; }
set
{
Nbr_Objet = value;
RaisePropertyChanged("nbr_objet");
}
}
public Objets(string Designation, float Prix, string imageUrl, int Nbr_Objet)
{
this.Designation = Designation;
this.Prix = Prix;
this.imageUrl = imageUrl;
this.Nbr_Objet = Nbr_Objet;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Update:
but I guess that it's like that I need a ViewModel of each created item ? so I guess what I really need to use is the ObservableCollection ..
You said that you have three categories, and each category have many items, If you display these in ListView, category is used as Group header, and I suggest you can use the same model for different item for different categories, then add in Observablecollection, because it have implemented INotifyPropertyChanged interface.
About ListView group, you can take a look:
https://github.com/xamarin/xamarin-forms-samples/tree/master/UserInterface/ListView/Grouping
If you still have another question, I suggest you can create new thread to ask, because this thread is very long.
Please remember to mark the helpful reply as answer, thanks.
to set a binding programatically
// set the BindingContext for the page
this.BindingContext = new MyViewModel();
// Title is a public property on MyViewModel
myLabel.SetBinding(Label.TextProperty, "Title");
in order for the UI to update when the VM is changed, the VM needs to implement INotifyPropertyChanged
This is some guidance that might help with your problem. Your code is messy and I think that is causing your confusion (you have several things named very similarly).
int Nbr_Objet;
public int nbr_objet { get{...} set {...}}
this.Nbr_Objet= Nbr_Objet;
this shows me that you are setting your member variable Nbr_Objet directly, when you do that the property change notification doesn't fire - you need to assign the value through the public nbr_objet for that to happen.
I'd suggest you define the binding in XAML, and make sure you bind to the property nbr_objet, not the private member variable (field) Nbr_Objet.
If you want to avoid confusion, follow the C# coding standard and name your member variable _nbrObjet, and camel case your property name public int NbrObjet { get {....
I'm creating a simple user registration form with fields to enter first name, last name, user name, password, and two combobox drop downs for major and concentration.
I believe I understand how to pass the enum data to the ComboBox, but not sure where (while file) to add the code.
Do I double click the ComboBox and add it there?
Do I create another class, add the enum data and code to display that data in the combobox there?
I believe I found out the way to add, here is my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public enum MajorList { Engineering = 1, Science, Humanities, Art, Business };
public enum EngConcentrations { Mechanical = 1, Electrical, Chemical, Civil };
public enum SciConcentrations { Computer, Biology };
public enum HumConcentrations { English, History };
public enum ArtConcentrations { Graphics, Painting, History, Music };
public enum BusConcentrations { Administration, Economics, Accounting };
private void Form1_Load_1(object sender, EventArgs e)
{
foreach (var item in Enum.GetValues(typeof(MajorList)))
{
majors.Items.Add(item);
}
}
}
Would it be possible to add one of the other enum based off of which major I selected?
For example, I select Engineering, and the second combobox would have the drop down of the Engineering concentrations?
It looks like you solved your original question. That code will add the values you want, and placing it in the form's Load event is fine.
As for the second question, yes, you could switch a second ComboBox based on the value selected in the "major" ComboBox. Subscribe to the SelectedValueChanged event:
void comboBox1_SelectedValueChanged(object sender, EventArgs e)
{
var selectedMajor = (MajorList)comboBox1.SelectedItem;
switch (selectedMajor)
{
case MajorList.Art:
// populate the second combo box with ArtConcentrations values
break;
case MajorList.Business:
// populate the second combo box with BusConcentrations values
break;
...
}
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);
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.
I have a list of custom objects which I have added to a ListBox control in my WinForms C# 4.0 application.
When the user selects a particular element in the ListBox, the properties of that object come up in the window next to the ListBox in various input fields. The user can change these and click 'Save' which will modify the data members of the objects to correspond with the changes the user has made.
The function does work. The values are saved to the object, and when the user selects the element again, their changes are confirmed to be saved correctly.
What isn't working is the update of the text in the ListBox. For example if we have a list of staff in the ListBox, and we can see "John Smith" there, we can click his name - edit his name to "John Smithe" and click OK. The ListBox still shows "John Smith", however if we click on his name, then in the TextBoxes on the right we can see that his name has correctly been changed to "John Smithe".
I have tried calling the Refresh() method on the ListBox but this didn't work.
I can fix it by removing the item from the ListBox and adding it again. This works, and it's not really an issue because the items are stored in separate lists anyway so I have no risk of losing any of my staff.
But is this really the best way to do it? Is there a more elegant way to update the text in the ListBox without removing/adding the item again?
Do the objects in the ListBox implement INotifyPropertyChanged?
Update:
It seems that you can solve the problem with a couple of steps:
Set the DisplayMember property of the ListBox to a property on your objects that provides whatever it is you want to appear in the list. I will assume this property is named DisplayText for this answer.
Have the objects implement INotifyPropertyChanged.
In the setters of all the properties that influence the value of DisplayText, raise the NotifyPropertyChanged event with DisplayText for the property name.
You should then be good to go.
Following the tutorial I reference above I made a quick and dirty example of using a BindingList. Hopefully it's helpful to you.
public partial class Listbox_Databinding : Form
{
BindingList<Person> People = new System.ComponentModel.BindingList<Person>();
public Listbox_Databinding()
{
InitializeComponent();
People.Add(new Person("John", "Smith"));
People.Add(new Person("John", "Jacob"));
lstSelectPerson.DataSource = People;
}
private void lstSelectPerson_SelectedIndexChanged(object sender, EventArgs e)
{
txtLast.Text = ((Person)lstSelectPerson.SelectedItem).Last;
}
private void btnUpdate_Click(object sender, EventArgs e)
{
((Person)lstSelectPerson.SelectedItem).Last = txtLast.Text;
}
}
public class Person : INotifyPropertyChanged
{
public Person(string first, string last)
{
First = first;
Last = last;
}
public override string ToString()
{
return Last + ", " + First;
}
string p_first;
string p_last;
public string First
{
get { return p_first; }
set
{
p_first = value;
OnDisplayPropertyChanged();
}
}
public string Last
{
get { return p_last; }
set
{
p_last = value;
OnDisplayPropertyChanged();
}
}
void OnDisplayPropertyChanged()
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("DisplayName"));
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}