c# listbox multiselect, selectedItems winforms - c#

I saw many examples of getting the values from selectedItems, but in my case I would like to somehow separate these values. What I mean is, for example if I have in my list options like work home forrest car, I would like to be able after choosing work and home to get both text separated and save them in some string variable.
Now I am doing it this way:
string text = "";
foreach (var item in customListBox1.SelectedItems)
{
text += item.ToString() + " ";
}
Later I am filtering datagridview based on this selecteditems in such way:
var result = list3.Where(Srodek => Srodek.Srodek.category1 == text);
That is why I need them separated. How can I do it?
If something is not clear, please let me know, I will try to explain it more.

You can do something better like this:
string text = string.Join(",", customListBox1.SelectedItems.OfType<Object>().Select(x => x.ToString()).ToArray());

var list = customListBox1.SelectedItems.Cast<string>().ToList();
var result = list3.Where(Srodek => list.Any(x=>x == Srodek.Srodek.category1));

Related

c# Linq: Replace empty string with some value

I have a list as:
var myList = lookuplist;
//where lookupList
Count = 2
[0]: "36"
[1]: ""
Above list is basically being populated by parsing from my excel file. Sorry the code before this is not relevant so not showing that.
My issue is I want to update the empty string with a space. So I tried the code below:
myList .Where(w => w.Length == 0).Select(y=>y = " ").ToList();
But it does not changes anything.
Am I missing something here. I can use a forach to loop through my list but I want to use linq.
Sorry if this is trivial.
You have to assign the updated list back to the original variable. You can do something like this:
myList = myList.Select(y => string.IsNullOrEmpty(y) ? " " : y).ToList();

How to search through combobox with a string containing a wildcat?

I have a combo-box that contains lots of entries like this small extract
1R09ST75057
1R11ST75070
1R15ST75086
1R23ST75090
2R05HS75063
2R05ST75063
3R05ST75086
2R07HS75086
The user now enters some information in the form that result in a string being produced that has a wildcat (unknown) character in it at the second character position
3?05ST75086
I now want to take this string and search\filter through the combo-box list and be left with this item as selected or a small set of strings.
If I know the string without the wildcat I can use the following to select it in the Combo-box.
cmbobx_axrs75.SelectedIndex = cmbobx_axrs75.Items.IndexOf("2R05HS75063");
I thought I could first create a small subset that all have the first char the same then make a substring of each minus the first two chars and check this but I can have a large amount of entries and this will take too much time there must be an easier way?
Any ideas how I can do this with the wildcat in the string please?
Added info:
I want to end up with the selected item in the Combobox matching my string.
I choose from items on the form and result in string 3?05ST75086. I now want to take this and search to find which one it is and select it. So from list below
1R05ST75086
2R05ST75086
3R05ST75086
6R05ST75086
3R05GT75086
3R05ST75186
I would end up with selected item in Combo-box as
3R05ST75086
You could use regular expressions. Something like this:
string[] data = new string[]
{
"1R09ST75057",
"1R11ST75070",
"1R15ST75086",
"1R23ST75090",
"2R05HS75063",
"2R05ST75063",
"3R05ST75086",
"2R07HS75086"
};
string pattern = "3*05ST75086";
string[] results = data
.Where(x => System.Text.RegularExpressions.Regex.IsMatch(x, pattern))
.ToArray();
You can use a regular expression for this task. First, you need a method to convert your pattern string to Regex like this (it should handle "*" and "?" wildcards):
private static string ConvertWildCardToRegex(string value)
{
return "^" + Regex.Escape(value).Replace("\\?", ".").Replace("\\*", ".*") + "$";
}
Then you will use it like the following:
List<string> comboBoxValues = new List<string>()
{
"1R09ST75057",
"1R11ST75070",
"1R15ST75086",
"1R23ST75090",
"2R05HS75063",
"2R05ST75063",
"3R05ST75086",
"2R07HS75086"
};
string searchPattern = "3?05ST75086";
string patternAsRegex = ConvertWildCardToRegex(searchPattern);
var selected = comboBoxValues.FirstOrDefault(c => Regex.IsMatch(c, patternAsRegex));
if (selected != null)
{
int selectedIndex = comboBoxValues.IndexOf(selected);
}
This assumes you only care about first found match. If you need all matches then substitute FirstOrDefault(...) with Where(...) clause and swap "if" statement with a foreach loop.
Thanks to all that helped I used a combination of items from all answers so everyone helped me answer this.
I added this function from the answers as it seems a good idea, thanks
private static string ConvertWildCardToRegex(string value)
{
return "^" + Regex.Escape(value).Replace("\\?", ".").Replace("\\*", ".*") + "$";
}
Then I get the combo box items into a list. I search the list and make some more decisions based on the result of the search.
List<string> comboBoxValues = new List<string>();
for (int i = 0; i < cmbobx_in_focus.Items.Count; i++)
{
comboBoxValues.Add(cmbobx_in_focus.GetItemText(cmbobx_in_focus.Items[i]));
}
string[] results = comboBoxValues
.Where(x => Regex.IsMatch(x, ConvertWildCardToRegex(lbl_raster_used.Text)))
.ToArray();
I now have array called results which is easy to work with.

Remove lines from List<String[]> using Linq, if meeting a certain criteria

I've searched around for a solution to this question but can't find an applicable circumstance and can't get my head around it either.
I've got a List<String[]> object (a parsed CSV file) and want to remove any rows if the first value in the row is equal to my criteria.
I've tried the following (with variations) and can't seem to get it to delete the lines, it just passes over them:
rows.RemoveAll(s => s[0].ToString() != "Test");
Which I'm currently reading as, remove s if s[0] (the first value in the row) does not equal "Test".
Can someone point me in the right direction for this?
Thanks, Al.
Edit for wider context / better understanding:
The code is as follows:
private void CleanUpCSV(string path)
{
List<string[]> rows = File.ReadAllLines(path).Select(x => x.Split(',')).ToList();
rows.RemoveAll(s => s[0] != "Test");
using (StreamWriter writer = new StreamWriter(path, false))
{
foreach (var row in rows)
{
writer.WriteLine(row);
}
}
}
So the question is -> Why won't this remove the lines that do not start with "Test" and upon writing, why is it returning System.String[] as all the values?
Did you try with Where? Where is going to filter based on a predicate. You should be able to do something like this:
Demo: Try it online!
List<string[]> rows = new List<string[]> { new []{"Test"}, new []{ "Foo"} };
rows = rows.Where(s => s[0] == "Test").ToList();
foreach(var row in rows)
{
Console.WriteLine(string.Join(",", row));
}
output
Test
You dont need ToString() because S[0] is already a string
You may want to handle empty case or s[0] could throw
You can use s.First() instead of s[0]
You can learn more about Predicateon msdn
Edit
For your example:
private void CleanUpCSV(string path)
{
var rows = File.ReadAllLines(path).Select(x => x.Split(','));
using (StreamWriter writer = new StreamWriter(path, false))
{
foreach (var row in rows.Where(s => s[0] == "Test"))
{
writer.WriteLine(string.Join(",", row));
}
}
}
By the way, you may want to use a library to handle csv parsing. I personally use CsvHelper
The only error in your code is the following:
Since row is string[] this
writer.WriteLine(row);
won't give you the result you were expecting.
Change it like this
writer.WriteLine(String.Join(",", row));
To convert the string[]back into its orginal form.
Any other "optimisation" in all the answers proposed here arent really optimal either.
If you're really trying to remove items where the first element isn't "Test", then your code should work, though you don't need to call .ToString() on s[0] since it's already a string. If this doesn't work for you, perhaps your problem lurks elsewhere? If you give an example of your code in a wider context you could get more help
Filter it like this instead:
var filteredList = rows.Where(s => s[0] == "test").ToArray();

Place contents of IList into a label?

I'm trying to find a way to print the results of an IList into a label so I can see what exactly is being returned. I need to check the info stored in the IList in order to see if anything is amiss.
IList<OrderItem> orderItems
If I wanted to put the contents of orderItems into a label, how would I do that? Do I need String.Join? Do I need a foreach?
I would suggest building an IEnumerable<string> from your order items, then turn that into a single string via String.Join:
// This formats each item as ID:Name
var itemsAsText = orderItems.Select(item => string.Format("{0}:{1}", item.ID, item.Name));
label.Text = string.Join(", ", itemsAsText);
List<OrderItem> tmp = orderedItems as List<OrderItem>;
tmp.ForEach(a => this.Label1.Text += a.PropertyHere.ToString());

Selected Checkbox from a bunch of checkboxes in .c#.net

The problem is faced under c# .NET, Visual Studio, Windows Form Application
I have a bunch of checkboxes placed randomly in one form and in one panel.
So, If any checkbox is selected in the form its value is supposed to be added up.
Bottomline: Instead of using plenty of "If-else loops", to evaluate whether its been checked or not. I wanna simplify it using a "for loop ".
Is there any Checkbox group name type feature, which I can use???
I wanna code something like this:
for(int i=0;i<checkboxes.length;i++)
{
string str;
if(chkbox.checked)
{
str+=chkbox.value;
}
}
Where checkboxes is a group name.
You can use a simple LINQ query
var checked_boxes = yourControl.Controls.OfType<CheckBox>().Where(c => c.Checked);
where yourControl is the control containing your checkboxes.
checked_boxes is now an object which implements IEnumerable<CheckBox> that represents the query. Usually you want to iterate over this query with an foreach loop:
foreach(CheckBox cbx in checked_boxes)
{
}
You also can convert this query to a list (List<Checkbox>) by calling .ToList(), either on checked_boxes or directly after the Where(...).
Since you want to concatenate the Text of the checkboxes to a single string, you could use String.Join.
var checked_texts = yourControl.Controls.OfType<CheckBox>()
.Where(c => c.Checked)
.OrderBy(c => c.Text)
.Select(c => c.Text);
var allCheckedAsString = String.Join("", checked_texts);
I also added an OrderBy clause to ensure the checkboxes are sorted by their Text.
CheckBox[] box = new CheckBox[4];
box[0] = checkBox1;
box[1] = checkBox2;
box[2] = checkBox3;
box[3] = checkBox4;
for(int i=0; i<box.length; i++)
{
string str;
if(box[i].checked== true)
{
str += i.value;
}
}
I think this code will work with DotNet4.0. Plz let me know any error occurs. Treat 'box' as regular array.
If all the checkboxes are in a groupbox you can do this:
foreach(Control c in myGroupBox.Controls)
{
if (c is CheckBox)
{
//do something
CheckBox temp = (CheckBox)c;
if(temp.Checked)
//its checked
}
}
Subscribe all checkboxes to one CheckedChanged event handler and build your string when any checkbox checked or unchecked. Following query will build string, containing names of all Form's checked checkboxes:
private void Checkbox_CheckedChanged(object sender, EventArgs e)
{
// this will use all checkboxes on Form
string str = Controls.OfType<CheckBox>()
.Where(ch => ch.Checked)
.Aggregate(new StringBuilder(),
(sb, ch) => sb.Append(ch.Name),
sb => sb.ToString());
// use string
}
I suppose other than subscribing to event CheckedChanged there is no alternative even if it is contained in some panel or form, You have to use if else,
if it would have been web base eg asp.net or php we could use jquery because it gives us the option to loop through each particular event using .each and getting its value

Categories