Removing text from RichTextBox is not working - c#

I am trying to remove characters from current cursor position to start of the string. It's working fine in simple TextBox
if (e.KeyCode == Keys.F2)
{
int LineNumber = txtDescription___.GetLineFromCharIndex(txtDescription___.SelectionStart);
txtDescription___.Text = txtDescription___.Text.Remove(0, txtDescription___.SelectionStart - 0);
}
But when I am trying to execute this code with RichTextBox it works on Text not on RTF and removes all styles. So I tried this code
if (e.KeyCode == Keys.F2)
{
int LineNumber = txtDescription___.GetLineFromCharIndex(txtDescription___.SelectionStart);
txtDescription___.Rtf = txtDescription___.Rtf.Remove(0, txtDescription___.SelectionStart - 0);
}
Now It's showing the following error
File Format is not valid
Can someone suggest me. How can I perform same code with RTF?

Try the below code,
if (e.KeyCode == Keys.F2)
{
int began = rtbDescription___.SelectionStart;
rtbDescription___.SelectionLength = began;
rtbDescription___.SelectedText = "";
}

Related

How to use DataGridView value as save & load control in C#?

I'm currently making save & load options program with DataGridView. the save button will save picturebox coordinates to make lines based on what already drawn on the picturebox. Multiple save datas are saved as tables in DataGridView. When loaded, the saved coordinates in tables go back to the screen and draw the saved coordinate lines. in the future gonna make the save data can be exported & imported to excel files but for now those buttons is not working yet.
Questions is How to make multiple loads possible? the first save data can be loaded properly after click but the 2nd and next will make the app crashed so the only working save data are the top ones. the error always points to string lineCell = dataGridView1.SelectedRows[rowIndex].Cells[1].Value.ToString(); but I dont know how to fix it
also if have suggestions how to export & import it to excel file please tell me. Thank you very much.
More or less the app is like this
used code for load & delete buttons in datagridview
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
var senderGrid = (DataGridView)sender;
int rowIndex = dataGridView1.CurrentCell.RowIndex;
if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >= 0)
{
if (e.ColumnIndex == dataGridView1.Columns[7].Index)
{
string lineCell = dataGridView1.SelectedRows[rowIndex].Cells[1].Value.ToString();
int x1Cell = Convert.ToInt16(dataGridView1.SelectedRows[rowIndex].Cells[3].Value.ToString());
int y1Cell = Convert.ToInt16(dataGridView1.SelectedRows[rowIndex].Cells[4].Value.ToString());
int x2Cell = Convert.ToInt16(dataGridView1.SelectedRows[rowIndex].Cells[5].Value.ToString());
int y2Cell = Convert.ToInt16(dataGridView1.SelectedRows[rowIndex].Cells[6].Value.ToString());
if (lineCell == "Black")
{
lineComboBox.SelectedIndex = 0;
line1X1 = x1Cell;
line1Y1 = y1Cell;
line1X2 = x2Cell;
line1Y2 = y2Cell;
}
else if (lineCell == "Red")
{
lineComboBox.SelectedIndex = 1;
line2X1 = x1Cell;
line2Y1 = y1Cell;
line2X2 = x2Cell;
line2Y2 = y2Cell;
}
else if (lineCell == "Yellow")
{
lineComboBox.SelectedIndex = 2;
line3X1 = x1Cell;
line3Y1 = y1Cell;
line3X2 = x2Cell;
line3Y2 = y2Cell;
}
lineComboBox.Refresh();
pictureBox1.Refresh();
}
else if (e.ColumnIndex == dataGridView1.Columns[8].Index)
{
dataGridView1.Rows.RemoveAt(rowIndex);
}
}
Save Button code
private void saveButton_Click(object sender, EventArgs e)
{
int index = dataGridView1.Rows.Add();
dataGridView1.Rows[index].Cells[0].Value = "Save " + index.ToString();
dataGridView1.Rows[index].Cells[2].Value = ang;
if(lineComboBox.SelectedIndex == 0)
{
dataGridView1.Rows[index].Cells[1].Value = "Black";
dataGridView1.Rows[index].Cells[3].Value = line1X1;
dataGridView1.Rows[index].Cells[4].Value = line1Y1;
dataGridView1.Rows[index].Cells[5].Value = line1X2;
dataGridView1.Rows[index].Cells[6].Value = line1Y2;
}
else if(lineComboBox.SelectedIndex == 1)
{
dataGridView1.Rows[index].Cells[1].Value = "Red";
dataGridView1.Rows[index].Cells[3].Value = line2X1;
dataGridView1.Rows[index].Cells[4].Value = line2Y1;
dataGridView1.Rows[index].Cells[5].Value = line2X2;
dataGridView1.Rows[index].Cells[6].Value = line2Y2;
}
else if (lineComboBox.SelectedIndex == 2)
{
dataGridView1.Rows[index].Cells[1].Value = "Yellow";
dataGridView1.Rows[index].Cells[3].Value = line3X1;
dataGridView1.Rows[index].Cells[4].Value = line3Y1;
dataGridView1.Rows[index].Cells[5].Value = line3X2;
dataGridView1.Rows[index].Cells[6].Value = line3Y2;
}
}
and this is the error message. Sorry its in japanese the office only use japanese version here. but its roughly translated as this
Unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
Additional Information: Index out of range. Must be non-negative and less than the size of the collection.

How to create a code from comboboxes using substring in c# visual studio?

So I'm doing a coursework in school about a music school and one thing I want to do is to be able to create a tuition code (made up of 6 characters) from 3 entered values.
So cbInstrument is a combobox, cbLevel is also a combobox and rb10Lessons/rb20Lesoons are radio buttons. When the code is running I want to be able to create a tuitionCode from these values as I choose them so that the tuition code would show up in a label of that same form as I choose the information.
For example; if in running form for instrument I click 'Cello', TuitionCode Shows up as CEL. Then after that if I click Level as 'Grade 1', TuitionCode shows up as CELB. And then if I choose 10 lessons then TuitionCode = CELB10.
Here is a sample of the code:
private void Tuition_Click(object sender, EventArgs e)
{
string code = "";
string codePart1 = code.Substring(0, 3);
string codePart2 = code.Substring(3, 1);
string codePart3 = code.Substring(4, 2);
if (cbInstrument.Text == "Cello")
{
codePart1 = "CEL";
}
else if (cbInstrument.Text == "Clarinet")
{
codePart1 = "CLA";
}
else if (cbInstrument.Text == "Double Bass")
{
codePart1 = "DBA";
}
if ((cbLevel.Text == "None") || (cbLevel.Text == "Grade 1") || (cbLevel.Text == "Grade 2"))
{
codePart2 = "B";
}
else if ((cbLevel.Text == "Grade 3") || (cbLevel.Text == "Grade 4") || (cbLevel.Text == "Grade 5"))
{
codePart2 = "I";
}
if (rb10Lessons.Checked)
{
codePart3 = "10";
}
else if (rb20Lessons.Checked)
{
codePart3 = "20";
}
lblTuitionCode.Text = code;
}
You are using the wrong function ... Subtring will return a substring within a string: for example : "123456".Substring(2,1)" will return "3"
What you need is simply to aggregate your string :
code = string.Format("{0}{1}{2}", codePart1, codePart2, codePart3);
that's it
The return value of Substring is its own string, not a reference to part of the string passed to it.
C# 6 has a feature called string interpolation which looks like this:
code = $"{codePart1}{codePart2}{codePart3}";
You could also use String.Format(...) if your VS version doesn't support C# 6 features.

Is there a way to use a variable in a catch block that was previously assigned in a try block?

So I've just been making a basic little calculator made up of buttons and a textbox(tbxSum).
The problem I'm having is that if an invalid sum is input I want my catch block to pick it up(which it does) and replace what's in the textbox with the most recent result in the calculator(which it doesn't).
So say I say:
3+3=6
My calculator will now put 6 in the textbox for the next sum.
So then say I did:
6//3
It's invalid which the calculator picks up, but I want the textbox value to return to 6 from the previous sum.
This is what I've tried:
var myButton = (Button)sender;
if (myButton.Content.ToString() == "=")
{
DataTable dt = new DataTable();
string s = tbxSum.Text;
string result = "";
if (s.Contains("("))
{
s = s.Replace("(", "*(");
}
try
{
var v = dt.Compute(s, "");
tbkSum.Text = s + "=" + v.ToString();
tbxSum.Text = v.ToString();
}
catch
{
MessageBox.Show("Invalid Sum");
tbxSum.Text = result;
}
}
I also have a textblock(tbkSum) which shows the previous sum so I thought maybe I could take everything in there to the right of the equals sign but I have no idea how to do that.
class Calculate(){
private boolean lastGoodValueSet = false;
private int lastGoodValue = 0;
void buttonFunction(){
if (myButton.Content.ToString() == "=")
{
//Your code
try
{
var v = dt.Compute(s, "");
tbkSum.Text = s + "=" + v.ToString();
lastGoodValue = v;
lastGoodValueSet = true;
}
catch
{
MessageBox.Show("Invalid Sum");
tbxSum.Text = result;
if (lastGoodValueSet)
tbxSum.Text = lastGoodValue;
}
}
}
}
This is an example set of code you could use, it's a simple value that you have to store to say if a good computation has been done and if so, at the point of error we want to go back to the computation. Hope that helps! You'll want to put some kind of message to the user, so they know there was an error though.
We have to do this, as at the point of the user pressing the equals button, the value has already changed inside tbkSum, we need it before the user has changed the value, so the best time to grab it is at the point when we update the tbkSum text value at a successful calculation
This is also assuming you do not create a new instance of the Calculate class each time you do your computation. Otherwise you'd need to store the number somewhere else
EDIT
The other way to fix this issue is to instead prevent the duplicate in the first place, I read from your other comments that you control what goes into the text box by buttons on the application. Assuming all buttons go through the same method of buttonFunction() then you could do:
private char[] buttonChars = {'/','*', '+'/*e.t.c*/}
void buttonFunction(){
string buttonPressedStr = myButton.Content.ToString();
char buttonPressed = buttonPressedStr[0];
int pos = Array.IndexOf(buttonChars , buttonPressed);
if (pos > -1)
{
if (tbxSum.Text.Length > 0){
char last = tbxSum.Text[tbxSum.Text.Length - 1];
pos = Array.IndexOf(buttonChars , last);
}
else
pos = 0;
if (pos > -1){
tbkSum.Text += buttonPressedStr;
}
}
There are cleaner ways to do this, but it's an example of how you could have prevented your issue in the first place. Some explanation:
buttonChars is an array of your different button types that would be appended to your text in the box, an example is +, -, and so on
First it checks if the button pressed was in your collection of specified buttonChars
If so, we have to check what the last thing added to the tbxSum was
If the last thing added to tbxSum was again found in the buttonChars array, we don't want to append a string
Otherwise, if the tbxSum was empty or had another character at the end, we can append our character
You can store the old value in a variable declard outside the try block and use this variable in your catch block again:
string oldSumValue = tbxSum.Text;
try
{
// your code
}
catch
{
tbxSum.Text = oldSumValue ;
MessageBox.Show("Invalid Sum");
}
Alternatively I've come up with this to prevent there being:
A)Duplicate of '*' or '/'
B)Sum starting with '*' or '/'
public MainWindow()
{
InitializeComponent();
if (tbxSum.Text == "")
{
btnDiv.IsEnabled = false;
btnMult.IsEnabled = false;
}
}
protected void btnSumClick(object sender, EventArgs e)
{
btnDiv.IsEnabled = true;
btnMult.IsEnabled = true;
var myButton = (Button)sender;
int pos = tbxSum.Text.Length;
if (pos > 0)
{
if ((tbxSum.Text[pos - 1] == '/' || tbxSum.Text[pos - 1] == '*') &&
(myButton.Content.ToString() == "/" || myButton.Content.ToString() == "*"))
{
int location = tbxSum.Text.Length - 1;
tbxSum.Text = tbxSum.Text.Remove(location, 1);
}
}
}

DataGridView attempting to save bound data with formatted value?

I am attempting to format a time value from a mssql database. The value is stored in the database as an int with hhmm as the format(for example: 1900 or 2130) I am unable to edit the database format as it is used by other software as well.
It is automatically bound to the DataGridView, and this has worked perfectly. However the specification I am working to says that it MUST show as a standard time format. So I have used the CellFormatting Event to show the times like 19:00 and 21:30.
It shows the value fine, however when I go to edit this value using the DataGridView it doesn't change it back to the unformatted value so I get the formatted value in the edit box. If I don't remove the colon I get an exception about saying Input is Invalid.
It was my understanding that the formatted value and the true value are not the same and this wouldn't cause an issue.
My code for formatting his below:
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex == -1)
return;
string CellName = dataGridView1.Columns[e.ColumnIndex].Name;
if (timeFormattedCells.Contains(CellName))
{
if (e.Value != null)
{
try
{
string currentFormat = e.Value.ToString();
if (currentFormat.Length == 3)
{
currentFormat = "0" + currentFormat;
}
DateTime dateTime = DateTime.ParseExact(currentFormat, "HHmm",CultureInfo.InvariantCulture);
currentFormat = dateTime.ToShortTimeString();
e.Value = currentFormat;
e.FormattingApplied = true;
}
catch (FormatException)
{
e.FormattingApplied = false;
}
}
}
}
I also need to ensure that the user cannot put an invalid time like 2405 or 1299.
Does anyone have a suggestion that might help me out?
Thanks
As long as your CellFormatting event is formatting the way you want, I would probably check the validity of the time first and then convert it to int...I would try something like this:
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
bool valid;
DataGridView dgv = (DataGridView)sender;
DataGridViewCell cell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex];
// Regex pattern acceptable for a time format
Regex timeRegex = new Regex("^([0-1]?[0-9]|[2][0-3]):([0-5][0-9])$");
if (cell.Value == null || cell.Value.ToString() == string.Empty)
{
cell.Style.BackColor = Color.White;
cell.ToolTipText = string.Empty;
cell.Tag = "empty";
valid = false;
}
// If the regex does not match then the format is invalid
else if (!timeRegex.IsMatch(cell.Value.ToString()))
{
cell.Style.BackColor = Color.Beige;
cell.ToolTipText = "Invalid format.";
cell.Tag = "invalid";
valid = false;
}
else
{
cell.Style.BackColor = Color.White;
cell.ToolTipText = string.Empty;
cell.Tag = "valid";
valid = true;
}
if(valid)
{
string timeToConvert = cell.Value.ToString();
string timeConvertReady = timeToConvert.Replace(":", "");
int timeAsInt = Convert.ToInt32(timeConvertReady);
updateTimeInDatabase(timeAsInt);
}
}
updateTimeInDatabase(timeAsInt) would be a method that sends the update command. This could also be a TableAdpater method or whatever you are using. If it was a TableAdapter the syntax would look something like testTableAdapter.Update(timeAsInt);

How to replace last comment by SelectedText

im working on a editor and i want to replace last comment after the intellisense appears .
further more heres the senario,
i got richtextbox(rtb) which served as the code-editor, and a hidden combobox(lb) which served as the intellisense . everytime i type words from richtextbox(rtb), sample i type "as", combobox will appear (like a intellisense) with keywords that starts from "as" .
all functions are working now except for after i select an item from combobox
sample string(combo box items): asd, asdf, asdfg .
then suppose to be i type as in richtextbox then i select 'asd' from combobox, then when i press enter the output would be:
as asd
instead of:
as (only)
further more heres my keyevents code:
void lb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
lb.Visible = false;
lb.Items.Clear();
}
if (e.KeyCode == Keys.Enter)
{
int start = 0, end = 0;
String line = rtb.Text.Substring(start, start - end);
int index = start;
string comment = line.Substring(index);
rtb.SelectedText = lb.SelectedText.ToString();
}
}
note: i just write:
rtb.SelectedText = comment + " " + lb.SelectedText.ToString();
for now to see some other function but that line was i the one i want to fix . also i even try:
rtb.SelectedText = comment - lb.SelectedText.ToString();
but it says Operator '-' cannot be applied to operands of type 'string' and 'string'
really thanks for the help in advance .
parameter:
if (token == "letterA" || token.StartsWith("Ab") || token.StartsWith("ab") || token.StartsWith("AB"))
{
int length = line.Length - (index - start);
string commentText = rtb.Text.Substring(index, length);
rtb.SelectionStart = index;
rtb.SelectionLength = length;
lb.Visible = true;
KeyWord keywordsHint = new KeyWord();
foreach (string str in keywordsHint.ab)
{
lb.Items.Add(str);
lb.SelectedIndex = lb.FindStringExact(str);
}
//token.Replace(lb.SelectedText,"");
}
I think this question/answer might be the problem:
ComboBox.SelectedText doesn't give me the SelectedText
Try using:
rbt.SelectedText = comment + " " + lb.Text
instead of SelectedText.

Categories