Linqy no matchy - c#

Maybe it's something I'm doing wrong. I'm just learning Linq because I'm bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control.
usage: enter text into textbox, click button. program lets you select a file to match the textbox value against and returns matches in label control.
code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace LinqTests
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected internal String[]
Content;
public String
Value;
private void button1_Click(object sender, EventArgs e)
{
Value = textBox1.Text;
OpenFileDialog ofile = new OpenFileDialog();
ofile.Title = "Open File";
ofile.Filter = "All Files (*.*)|*.*";
if (ofile.ShowDialog() == DialogResult.OK)
{
Content =
File.ReadAllLines(ofile.FileName);
IEnumerable<String> Query =
from instance in Content
where instance == Value
orderby instance
select instance;
foreach (String Item in Query)
label1.Text +=
Item + Environment.NewLine;
}
else Application.DoEvents();
ofile.Dispose();
}
}
}
The Problem
What I have above works perfectly, except for one thing. I have a file that I check against which contains the following text:
File:
jason
is
the
funniest
person
in
the
world
jason
jason
jason
pezzimenti
... And it never, ever returns "jason". but it will always return any other word in there.
I'm guessing that it doesn't return a match if there is more that one of the same match?
Would I be correct in saying so? And is this how it's supposed to be? And how would you suggest I make it always return a match no matter how many of the same matches there are. I mean I would have thought that it would return the following output, based on the code above... isn't that what the foreach(Item in Query) is for?, when i type "jason" into the textBox1:
jason
jason
jason
jason
..but it doesn't return any jasons :(

You probably have a blank at the end of the line... try that instead :
IEnumerable<String> Query =
from instance in Content
where instance.Trim() == Value.Trim()
orderby instance
select instance;

You are correct in what you expect to happen, ie, you would get one line displayed per instance of the word in the text file.
It could be that you have blank spaces at the end of your file, as Thomas Levesque has stated, but it could also be that your file does not have the line endings that File.ReadAllLines() is expecting. It expects CRLF endings, so if you have only LF endings for example, you might fine that the method only returns one "line".

Related

C# CheckedListBox how to manipulate checked data?

Hey guys new to C# and I am trying to setup a GUI, all I want the GUI to do is have a simple file explorer with a CheckedListBox to represent selected files.
I can get the CheckedListBox to show up and click on files but I'm not sure how to continue from here, most tutorials stop here, or go too advanced with tree view and other things that seem unnecessary for what I am trying to do.
Here is my code:
Any help is appreciated and if you guys could point me in the right direction that would be awesome.
EDIT:
To rephrase my question:
I want the user to select files through the CheckedListBox (user input stops here), and for those selected files to be put in a list that my code can manipulate.
Not sure how to accomplish this after my first foreach loop (which adds all files in the selected directory to the CheckedListBox for user selection).
The second foreach loop is an attempt at this, manipulating the files so that they output their filenames after being selected. However no Messagebox shows up and I assume that their is a disconnect between the user selecting files and the codes attempt at manipulating said files.
Second Edit:
I think I figured it out I made a second button and from here it looks like I can manipulate the chosen files however I want.
Currently the code is working the way I would expect it to work.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace SelectFiles
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
checkedListBox1.CheckOnClick = true;
}
private void button1_Click(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
MessageBox.Show(fbd.SelectedPath);
checkedListBox1.Items.Clear();
string[] files = Directory.GetFiles(fbd.SelectedPath);
foreach (string file in files)
{
checkedListBox1.Items.Add(file);
}
}
private void button2_Click_1(object sender, EventArgs e)
{
List<string> list_all_excelfiles = new List<string>();
foreach (string item in checkedListBox1.CheckedItems)
{
list_all_excelfiles.Add(item);
MessageBox.Show(Path.GetFileName(item));
}
}
}
}
First i advice you to assign Value member and Display member for each item.
Display Member will be visible to user
Value Member will we use in code
To do this first create simple custom class
public class Int_String
{
public int _int { get; set; }
public string _string { get; set; }
}
Be careful because get; set; part is important to be there since if not code will not work
Now what you need to do is create list of items with custom class like this
class YourForm : Form
{
List<Int_String> myList = new List<Int_String>(); //Create list of our custom class
public YourForm()
{
PopulateMyList();
}
private void PopulateMyList()
{
//Here read from database or get data somehow and populate our list like this
//I will populate it manually but you do it in foreach loop
myList.Add(new Int_String { _int = 0, _string = "First Item" });
myList.Add(new Int_String { _int = 1, _string = "Second Item" });
myList.Add(new Int_String { _int = 2, _string = "Third Item" });
}
}
After that you need to assign this list to your checkedListBox which you will do like this:
public YourForm()
{
PopulateMyList();
checkedListBox1.DataSource = myList;
checkedListBox1.DisplayMember = "_string";
checkedListBox1.ValueMember = "_int";
}
And now when you can manipulate with checked items like this:
for(int i = 0; i < checkedListBox1.Items.Count; i++)
{
if(checkedListBox1.Items[i].CheckedState == CheckState.Checked)
{
int itemValueMember = (checkedListBox1.Items[i] as Int_String)._int;
int itemDisplayMember = (checkedListBox1.Items[i] as Int_String)._string;
//Use these two vars for whatever you need
}
}
TWO IMPORTANT TIPS:
I am not sure for this one since i am writing all this from head but i think that visual studio will not show you that there is DisplayMember or ValueMember for checkedBox component BUT also it will not show error. Reason is that they have hidden in intentionally for idk what reason but it will work.
You are able to assign Display and Value member to a lot of components in winforms BUT for some reason checkedListBox is specific. It is specific because you MUST first assign DataSource to it and then tell it checkedListBox.DisplayMember = "_string" ...... For new guy you will ask why it is important. Simple answer is create custom list for test and add 10k items inside it and then first declare datasource and after it Display and Value member. Test how long form will need to load (get out of freeze state). After that do everything same but first declare Display and Value member and then assign datasource and test again. I am telling this from head without testing but before when i needed about 5k rows with 1st solution it took me about 30 sec and second < 1 sec. If you want to know more about it google it but for now this is pretty much info for you.

"Input string was not in a correct format."

I am working on a project in which I have a form through which I can edit a question available in a list view. Whenever I select a row from the list view and click on the 'modify' button, the text boxes above the list view load the question and its options.
This means that when I select a row in the list view and click on the 'modify' button, the question loads itself into the text boxes. I edit the question there and click on 'save' to save changes, but I am not able to access the data in the text boxes. It says {"Input string was not in a correct format."}.
My code of the form frmFormWizard's 'edit' button is given below:
frmFormWizard.cs Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Sql;
using System.Data.SqlClient;
namespace SurveyBuilder
{
public partial class frmFormWizard : Form
{
int intPanelNumber = 1;
Boolean blnCancel = false;
//int intFlag = 1;
public frmFormWizard()
{
InitializeComponent();
}
...
private void btnEditTwoOrMoreOptions_Click(object sender, EventArgs e)
{
int QuestionID;
string sql;
QuestionID = Convert.ToInt32(lvTwoOrMoreOptions.SelectedItems[0].Text.ToString());
{
SqlConnection cn = new SqlConnection();
SqlCommand rs = new SqlCommand();
SqlDataReader sdr = null;
clsConnection clsCon = new clsConnection();
clsCon.fnc_ConnectToDB(ref cn);
sql = "";
sql += "SELECT * FROM SurveyQuestionLog WHERE SurveyQuestionLog.QuestionLogID = "+ QuestionID +"";
//sql += "SELECT * FROM SurveyQuestionLog";
rs.Connection = cn;
rs.CommandText = sql;
sdr = rs.ExecuteReader();
while (sdr.Read())
{
txtTwoOrMoreQuestions.Text = (string)sdr["Question"];
txtOption1.Text = (string)sdr["Choice1"];
...
}
sdr.Close();
rs = null;
cn.Close();
}
}
Whenever I try to compile the code it says "{"Input string was not in a correct format."}" and this error is shown on the following line:
QuestionID = Convert.ToInt32(lvTwoOrMoreOptions.SelectedItems[0].Text.ToString());
Please let me know what I am doing wrong.
It looks like some space include in the text.
Use
lvTwoOrMoreOptions.SelectedItems[0].Text.ToString().Trim()
and convert to int32.
hope this code will solve you
From comments
if your ListView is in report mode (i.e. it looks like a grid) then you will need the SubItems property. lvTwoOrMoreOptions.SelectedItems gets you each items in the list view - SubItems gets you the columns. So lvTwoOrMoreOptions.SelectedItems[0].SubItems[0] is the first column value,
Please change your code like below.
int QuestionID;
bool IsIntValue = Int32.TryParse("YOUR-VARIABLE", out QuestionID);
if (IsIntValue)
{
// YOUR CODE HERE
}
Hope i will be help.
whenever i try to compile the code it says "{"Input string was not in a correct format."}"
This error won't come on compiling.
Now the error comese because you are trying to parse an invalid string to integer. To do it in a safe manner, you should do it like this
int questionID;
if(int.TryParse(vTwoOrMoreOptions.SelectedItems[0].Text.ToString(),out questionID))
{
//success code
}
else
{
//failure code
}
You might be trying to access a control inside a control, maybe a GridView or DetailsView.
Try using something like this:
empsalary = Convert.ToInt32(((TextBox)DetailsView1.Rows[1].Cells[1].Controls[0]).Text);
It looks that whatever that text is containing some characters which cannot be converted to integer like space, letters, special characters etc. Check what is coming through dropdown as below
lvTwoOrMoreOptions.SelectedItems[0].Text.ToString();
and see if that is the case.

Getting array of buttons to display data from a XML file?

So, my XML file is as follows:
<?xml version="1.0" encoding="utf-8" ?>
<quiz>
</answers>
</question>
<!-- More questions here -->
</quiz>
My Form1.cs looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Linq;
using System.Drawing;
namespace WindowsFormsApplication1
{
public partial class FormMain : Form
{
Basically, all four buttons had the question on them rather than the answers and underneath the bottom left button, there appeared to be a blank button. How do I get the question to display where label1 is and the answers to be on four separate buttons? Also, how will I do it when I start adding multiple questions (User obviously can't move on to the next question unless they get previous one right and difficulty can be chosen at the start to show a different set of questions).
I've been on at this for a while and I think it needs a fresh set of eyes because my relatively novice C# brain can't figure it out. Anyone help me please?
Check out the answer to this question. What is much easier to deal with is Deserialize the XML into a class you've created with a matching structure.
How to Deserialize XML document
More info here:
http://msdn.microsoft.com/en-us/library/58a18dwa.aspx
You are setting the text of every button each time around your loop:
foreach (var question in _questions)
{
button1.Text = question.QuestionText;
button2.Text = question.QuestionText;
button3.Text = question.QuestionText;
button4.Text = question.QuestionText;
}
The last time around the loop, each button will have the text set to the text of the last question.
It also looks a bit odd, as you have four buttons defined as fields of the form, yet you are creating additional buttons in your PopulateForm method but doing nothing with them.
You would be better off getting rid of the fields and working with the newly-created buttons directly:
private void PopulateForm()
{
int count = 0;
foreach (var question in _questions)
{
var button = new Button();
button.Size = new Size(60, 23);
button.Location = new Point(100, 40 + (count * 30));
button.Text = question.QuestionText;
Controls.Add(button);
count++;
}
}
You have to set the location of each button to something different, otherwise they will all show in the same place.
EDIT:
From looking at your code in your zip file, what you want is something like (assuming that your questions have four answers):
private void PopulateForm()
{
foreach (var question in _questions)
{
label1.Text = question.QuestionText;
button1.Text = question.Answers[0];
button2.Text = question.Answers[1];
button3.Text = question.Answers[2];
button4.Text = question.Answers[3];
}
}

How to save a listview of data to a .txt in C# so it can be accessed the next time the form is open?

How can I save the the data in a listview?
For example if the user has put something into the listview and then closes the application, all that information is then lost. Is there any way of saving the information as soon as they put something into the listView?
This is the code I use to input the information from a textbox to the listView1:
string[] items = { titletxt.Text, statustxt.Text };
ListViewItem lvi = new ListViewItem(items);
listView1.Items.Add(lvi);
UPDATE (29/12/2012)
Thanks for all the help! But I can't seem to get it working. I have created a really simple form to try and get it working. It has 3 textboxes (NameTxt, AgeTxt, HairColourTxt), a button, and the listview(ListOfPeople).
Here is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace listview
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string[] items = { NameTxt.Text, AgeTxt.Text, HairColourTxt.Text };
ListViewItem lvi = new ListViewItem(items);
ListOfPeople.Items.Add(lvi);
}
}
}
I have tried to add the code posted by #user574632 & #Joe & #DmitryKvochkin and I have changed bits but still cant get it to work. I'm not sure what I'm doing wrong? I have tried to add this:
private void saveListOfPeopleItems(string path, ListView lv)
{
var delimeteredListviewData = new List<string>();
foreach (ListViewItem lvi in lv.Items)
{
string delimeteredItems = string.Empty;
foreach (ListViewItem.ListViewSubItem lvsi in lvi.SubItems)
{
delimeteredItems += lvsi.Text + "#";
}
delimeteredListviewData.Add(delimeteredItems);
}
System.IO.File.WriteAllLines(path, delimeteredListviewData.ToArray());
}
private void loadListOfPeopleItems(string path, ListView lv)
{
foreach (string line in System.IO.File.ReadAllLines(path))
{
lv.Items.Add(new ListViewItem(line.Split(new char[] { '#' }, StringSplitOptions.RemoveEmptyEntries)));
}
}
You need to create the save logic, there's no automatic method.
The easiest way is to use Serialization (look for ISerializable) to save to a file of your choice (name it whatever you like): You can save entire objects this way. Here is a simple tutorial on serialization.
The other method is to parse the listview content into strings (keep only what you need), and you save the strings to a text file (TextReader and TextWriter).
If you want to save application settings (and not user data), have a look at this link, or this one which might be easier to read.
Finally, if you need to interact with the data you save regularly, or if you have a lot of data to store, use a database (SQL, mySQL, etc). The latter method is the longest one to implement.
if you want to save to a text file, you could use the following:
private void saveListViewItems(string path, ListView lv)
{
var delimeteredListviewData = new List<string>();
foreach (ListViewItem lvi in lv.Items)
{
string delimeteredItems = string.Empty;
foreach (ListViewItem.ListViewSubItem lvsi in lvi.SubItems)
{
delimeteredItems += lvsi.Text + "#";
}
delimeteredListviewData.Add(delimeteredItems);
}
System.IO.File.WriteAllLines(path, delimeteredListviewData.ToArray());
}
private void loadListViewItems(string path, ListView lv)
{
foreach (string line in System.IO.File.ReadAllLines(path))
{
lv.Items.Add(new ListViewItem(line.Split(new char[]{'#'}, StringSplitOptions.RemoveEmptyEntries)));
}
}
You can use integrated visual studio settings and than bind it to your listview, even in designer. After you changed your listview you can save them
I would say the answer is : use .txt files
Also you can create an SQL database, and save it there...

Make links readonly in richtextbox c#

I have a richtextbox in c# and I want to make the links that appear as readonly. Right now I can move my cursor into it and edit it. Is there any way to make it readonly?
You can set this property of a RichTextBox to make the whole text read-only
ReadOnly = true
If you would like to protect the links only but leave other text editable, please try to insert the following whether under Form1_Load or under any method you may create
You'll need to add RichTextBox.Find(string str); from the object browser
MatchCollection mc = Regex.Matches(richTextBox1.Text, #"(www[^ \s]+|http[^ \s]+)([\s]|$)", RegexOptions.IgnoreCase); // Create a new MatchCollection and match from richTextBox1.Text
for (int collection = 0; collection < mc.Count; collection++) // increase collection for every string in mc
{
if (richTextBox1.Find(mc[collection].Value, RichTextBoxFinds.None) > -1) // Find the mc value
{
richTextBox1.SelectionProtected = true; // Protect the value
}
}
So the form would look like this
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
MatchCollection mc = Regex.Matches(richTextBox1.Text, #"(www[^ \s]+|http[^ \s]+)([\s]|$)", RegexOptions.IgnoreCase);
for (int collection = 0; collection < mc.Count; collection++)
{
if (richTextBox1.Find(mc[collection].Value, RichTextBoxFinds.None) > -1)
{
richTextBox1.SelectionProtected = true;
}
}
}
}
}
Thanks,
Have a great day :)
You can change it in your code like this:
richTextBox1.ReadOnly = true;
Or you could go to your design view, check the properties for your richtextbox and set the ReadOnly attribute to true.
You should capture the change event, in such a way that you reset every change a user would like to make to the link and set it back to the original link. Save the positions of the links and update the positions if the user deletes or adds a character.
I would like to share my solution...I did try everything I found on the internet but seems I can't get exactly 100% like I want(to make a richtexbox as readonly). Then I start looking for an alternative which finally I get one to do exactly like I want.
Sometime we need to show the value with a style on it, thats why we choose richtextbox at the 1st time, then it become an issue when we unable to make it as ReadOnly. The different is I am not using the richtextbox anymore but I change it to label. Depending on how your program work, you might need to have 2 control (richtextbox & label) to hold the same value which will be switched(visible true/false) base on your requirement.
See my example here to get a ReadOnly richtextbox look alike control :
<div id="History">
<asp:Label ID="lblLACA27" runat="server" CssClass="ctlLabel"></asp:Label>
</div>
And a piece of CSS code :
#History
{
height: 100px;
float: left;
overflow: auto;
overflow-x: hidden;
}
The DIV tag which hold the LABEL will act like multiline textbox/richtextbox with scrollbar visible on it. Thats it & lets continue programming. Hope this will help someone later.

Categories

Resources