Generated a list of filenames, but no file paths - c#

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.

Related

Show ToString of a Collection Wrapper Class in DataGridView

I have a class that has one of its properties being of type ObservableCollection<string>
public class SizeList
{
public string ID { get; set; }
public string Name { get; set; }
//public ObservableCollection<string> List { get; set; }
public ListEntryCollection List { get; set; }
}
During a unit test I return a list of SizeList and then show it in a DataGridView to check the results I am expecting, the data is fine but I am missing the field List in the DGV; only the ID and Name are shown, so I have made a wrapper class for the ObservableCollection<string> and overriden its .ToString() method:
namespace System.Collections.ObjectModel
{
using System.Collections.Generic;
public class ListEntryCollection : ObservableCollection<string>
{
public ListEntryCollection(IEnumerable<string> collection)
: base(collection)
{
}
public override string ToString()
{
return Count.ToString() + ((Count > 1) ? " Entries": " Entry");
}
}
}
But I am still not getting the List field in the DGV, so what am I doing wrong ?
Per Column Types in the Windows Forms DataGridView Control, the only property types for which bound columns are automatically generated are numbers, text, booleans, and images.
To display other types, you need to add the column manually to the DataGridView, or use a custom column type (and even then, you'll probably have to add it manually.)
A couple of options present themselves:
You could try adding a read-only property to SizeList to display the description of the list, and see if that will result in a column being automatically created.
You can try adding a column manually, which I believe you can do in the Form Designer if you click on the DataGridView. You will probably have to override a method or two, or use an event handler, in order to change the display from the default. (It's possible, though, that it will use the ToString override you created, in which case the problem is solved.)
Or, you could create a ListSummaryDataGridViewColumn class, that can represent a list by display a count of the items in it, and add one of those manually.

Validating a large dictionary of set strings with user input

I have a profile form that has a lot of user selections and I am sort of stumped on a good approach to validate what the user enters, when passing validation mapping those values to object properties.
For example I have a dictionary
public static Dictionary<string, string> objProfileSelections = new Dictionary<string, string>();
public static string MySelections(string key)
{
objProfileSelections.Add("1", "No Answer");
objProfileSelections.Add("3", "Less Than $25,000");
objProfileSelections.Add("5", "$35,000 to $50,000");
objProfileSelections.Add("7", "$50,000 to $75,000");
objProfileSelections.Add("9", "$75,000 to $100,000");
objProfileSelections.Add("11", "$100,000 to $150,000");
objProfileSelections.Add("13", "$150,000+");
objProfileSelections.Add("2", "No Answer");
objProfileSelections.Add("4", "Less Than $25,000");
objProfileSelections.Add("6", "$35,000 to $50,000");
objProfileSelections.Add("8", "$50,000 to $75,000");
objProfileSelections.Add("10", "$75,000 to $100,000");
objProfileSelections.Add("12", "$100,000 to $150,000");
objProfileSelections.Add("14", "$150,000+");
string item;
objProfileSelections.TryGetValue(key, out item);
return item;
}
Id like to pass in a list of key strings from the user and pass those items to populate an object. The issue is I don't know how to code it so it know which property to go to, I looked at reflection, but I couldn't find any examples that have a set dictionary of values that map to property names.
To make a bit more clear, when a user makes a selection it passes as a parameter in the dictionary, and the dictionary outputs the items. From key 1 comes value No Answer. If the user selected all the check boxes it would be value - (1,3,5,7,9,11,13). I need to extract those values when there is a matching key to a matching property. For example if the user clicks 1,5 but leaves the rest unchecked, how do I know which selections the user made? How do I get the program to know which property to populate based on the results?
*edit
some properties I would like it mapped to
public string MyAnnualIncome{ get; set; }
public List<string> InterestAnnualIncome{ get; set; }
So the first property would be taking one value, and the second property would be taking multiple values.
When a key matches a value comes out the dictionary, I would need the odd values going to MyAnnualIncome and the even values going to InterestAnnualIncome.
so no one is confused odd and even keys are set up for a purpose, odd numbers belonging to a certain group of properties and the even ones belonging to another based on the html selections (even being my selections, odd being what I am interested in)
*Update
Is there a way I can possibly use the keys like 1,3,5 and pass that into a list using the except extension method. Then take the results and use a method to convert the values from enumerated data types to strings?
Hopefully I understood your question.
I would add a small helper class (this is a solution which doesn't use reflection, but uses delegates instead):
public class PropertyModifier
{
private string text;
private Func<string> modifier;
public PropertyModifier(Func<string> modifier)
{
this.modifier = modifier;
}
public PropertyModifier With(string text)
{
PropertyModifier newModifier = new PropertyModifier(modifier);
newModifier.text = text;
return newModifier;
}
public void Modify()
{
modifier(Text);
}
}
Then I would rewrite your code and have the dictionary map to this class instead to string:
public static Dictionary<string, PropertyModifier> objProfileSelections = new Dictionary<string, PropertyModifier>();
public static MyUserProfile Profile; //Assuming this is the object you want to modify
public static string MySelections(string key)
{
PropertyModifier myIncome = new PropertyModifier(text => Profile.MyAnnualIncome = text);
PropertyModifier interestIncome = new PropertyModifier(text => Profile.InterestAnnualIncome.Add(text));
objProfileSelections.Add("1", myIncome.With("No Answer"));
objProfileSelections.Add("3", myIncome.With("Less Than $25,000"));
...
objProfileSelections.Add("2", interestIncome.With("No Answer"));
objProfileSelections.Add("4", interestIncome.With("Less Than $25,000"));
...
}
Then, when processing the user's selection, get the mapped PropertyModifier from the dictionary and call its Modify method.
I tried in this code to illustrate how you can modify the properties of the different classes that may compose a profile. Modifications are done by reflection only, i.e. just providing the class name, the property name that will vary in each class and the string value to be assigned to the property.
Not sure that it fits your expectations :(
Profile profile = new Profile() ;
profile.SetPropertyValue("hair","color","brown") ;
internal class Profile()
{
private Hair hair_ = new Hair();
private Job job_ = new Job ();
internal Hair hair { get { return hair_ ; } }
internal Job job { get { return job_ ; } }
private void SetPropertyValue(string profileItemName, string ItemPropertyName, string value)
{ // it is assumed that the different items (hair or job) of the Profile are accessible
// with a a property
// first find the Item object, i.e. hair or job
object itemObj = this.GetType().GetProperty(profileItemName).GetValue(this,null);
// assign to Item property the input value, e.g. hair.color=Brown
itemObj.GetType().GetProperty(ItemPropertyName).SetValue(itemObj, value, null);
}
}
internal class Hair()
{
private string color_ ;
private string style_ ;
internal string color { get { return color_ ; } set {color_ = value ; } }
internal string style { get { return style_ ; } set {style_ = value ; } }
}

Navigate to page based on itemview clicked item

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);

Get index by value regarding combobox for win apps c#

we can easily get index of combobox using FindString method
int index = cboCountryTwoCode.FindString(localJob.DeliveryCountryTwoCode.Trim());
cboCountryTwoCode.SelectedIndex = index;
so i just need to know is there any way to get index of combobox just finding by value instead of finding by text. please let me know is there any similar. if anything not there then how to achieve my objective that get index of combobox just finding by value. thanks
this way i am populating my combo
cboCountryTwoCode.DataSource = Utility.LoadCountry();
cboCountryTwoCode.DisplayMember = "CData";
cboCountryTwoCode.ValueMember = "CValue";
LoadCountry() will return datatable . thanks
In WinForms, ComboBox doesn't have an explicit key/value list of items. It has an ObjectCollection for Items.
I think you could implement ToString() on your objects to display its proper descriptions.
Then you should use some LINQ to find the correct item. Something like this:
class MyType
{
public int Id { get; set; }
public string Description { get; set; }
public override string ToString()
{
return Description;
}
}
var selectedObject = cb.Items.Cast<MyType>().SingleOrDefault(i => i.Id.Equals(myId));

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