I'm trying to implement a custom text-editor in C# using the ScintillaNET component. I've got most of it right until now, but stuck at one point. I want to give the user the ability to block comment/uncomment the selected text. I tried a lot, but cannot find any examples online. The only thing I seem to get from the control's Selection object are the Start and End positions, but that isn't much help
private void commentBlockToolStripMenuItem_Click(object sender, EventArgs e)
{
if (txtSQL.Selection.Text.Length > 0)
{
String start = txtSQL.Selection.Start.ToString();
String end = txtSQL.Selection.End.ToString();
MessageBox.Show(start + "::" + end);
}
}
Were any of you able to successfully implement this using the ScintillaNET control?
EDIT:
After some improvization, I'm able to do it somehow, but after block is commented, last line moves out of selection!
private void commentBlockToolStripMenuItem_Click(object sender, EventArgs e)
{
if (txtSQL.Selection.Text.Length > 0)
{
Range range = txtSQL.Selection.Range;
int f = range.StartingLine.Number;
int t = range.EndingLine.Number;
int endpos = txtSQL.Selection.End;
for (int i = f; i <= t; i++)
{
//txtSQL.GoTo.Line(i);
string tstr = txtSQL.Lines[i].Text.Replace(Environment.NewLine, "");
txtSQL.Lines[i].Text = "--" + tstr;
}
}
}
After a bit of experimentation, I found a way to accomplish this. Though I doubt if it is the most elegant of solutions!
private void commentBlockToolStripMenuItem_Click(object sender, EventArgs e)
{
if (txtSQL.Selection.Text.Length > 0)
{
Range range = txtSQL.Selection.Range;
int f = range.StartingLine.Number;
int t = range.EndingLine.Number;
for (int i = f; i <= t; i++)
{
txtSQL.InsertText(txtSQL.Lines[i].StartPosition,"--");
}
txtSQL.Selection.Start = txtSQL.Lines[f].StartPosition;
txtSQL.Selection.End = txtSQL.Lines[t].EndPosition;
}
}
Actually I found a very simple solution to this. To block comment do
scintilla1.Lexing.LineComment();
And to block uncomment do
scintilla1.Lexing.LineUncomment();
Related
new to WPF so not sure if there is some sort of syntax that I am missing or what.
Course choice;
int totalCredits = 0;
int classesRegistered = 0;
string[] registeredCourses = new string[3];
private void button_Click(object sender, RoutedEventArgs e)
{
if (classesRegistered < 3)
{
choice = (Course)(this.comboBox.SelectedItem);
if ((!choice.Equals(registeredCourses[0]))
&& (!choice.Equals(registeredCourses[1]))
&& (!choice.Equals(registeredCourses[2])))
{
registeredCourses[classesRegistered] = choice.ToString();
this.listBox.Items.Add(registeredCourses[classesRegistered]);
classesRegistered = classesRegistered + 1;
}
}
}
So I don't want the choice to be added to the listbox if its already registered to one of the array's values. What is it I'm missing?
Your if statement is comparing a string to a Course object, you may change it to below:
if(!registeredCourses.Any(obj=> obj.Equals(choice.ToString())))
I am fairly new to C#.
I trying to create a Combo Box that displays numbers from 1-100 generated from the method below. I am using an example that found on the internet and modifying it to meet my needs.
I can't get my combo box to display anything. Please offer suggestions or a better way to execute my intended goal.
private void Range()
{
ArrayList arr = new ArrayList();
for (int i = 0; i <= 100; i++)
{
arr.Add(i);
}
}
public void FillInComboBox(ComboBox target, int start, int end)
{
for(int i = start; i <= end; i++)
{
target.Items.Add(i);
}
}
Usage
private void Form2_Load(object sender, EventArgs e)
{
FillInComboBox(comboBox1, 0, 100);
}
I want to navigate between some TreeViewItem using back/forward buttons. I can actually do that but my problem is that i can't make it stop going outside the limits. There's an example of my code for a forward button:
private void MainUser_button_next_Click(object sender, RoutedEventArgs e)
{
int index = 0;
foreach (TreeViewItem i in TreeviewUsers.Items)
{
if (i.Equals(MainTreeView.SelectedItem))
{
break;
}
index++;
}
(TreeviewUsers.Items[index + 1] as TreeViewItem).IsSelected = true;
}
With the code I'm showing above it is possible to navigate forward but it breaks after it gets more that it's limits. I know I need to bind a limit but I don't know where to do that!
Thanks in advance!
Here's a possible answer, depending on the behavior you want
(TreeviewUsers.Item[(index+1)%TreeviewUser.Item.Count] as TreeViewitem).IsSelected = true;
or this line (try for the back case)
(TreeviewUsers.Item[mod((index+1),TreeviewUser.Item.Count)] as TreeViewitem).IsSelected = true;
and define somewhere
int mod(int x, int m) {
int r = x%m;
return r<0 ? r+m : r;
}
By the way, can't you change this code
int index = 0;
foreach (TreeViewItem i in TreeviewUsers.Items)
{
if (i.Equals(MainTreeView.SelectedItem))
{
break;
}
index++;
}
with this here
int index = TreeviewUsers.Items.Select((v, i) => new {v, i}).Where(x => x.v.Equals(MainTreeView.SelectedItem)).Select(x => x.i);
I'm making a C# application including a RichTextBox in which the user will be able to put some C# code in it and format it by indents like what Visual Studio does.
private void btnEdit_Click(object sender, EventArgs e)
{
//rchCode.Text= formattedCode; // Which I haven't got anywhere so far
}
I looked for the same questions and this answer suggests using something called NArrange, but I don't want use other tools, add-ins or such.
Also this one offering the CodeDOM way which I haven't figure it out how to use it (If it's helpful in anyway)
I want to do it by writing some actual code. How can I do it?
To properly indent code you would need Microsoft.CodeAnalysis.CSharp nuget package and .NET framework 4.6+. Sample code:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
...
public string ArrangeUsingRoslyn(string csCode) {
var tree = CSharpSyntaxTree.ParseText(csCode);
var root = tree.GetRoot().NormalizeWhitespace();
var ret = root.ToFullString();
return ret;
}
One-liner:
csCode = CSharpSyntaxTree.ParseText(csCode).GetRoot().NormalizeWhitespace().ToFullString();
You may also use NArrange to sort methods in your cs file, organize usings, create regions, etc.
So I got the solution this way:
It's not still perfect (as it always add one or more new lines before the first code line). So if anyone can improve it or has a better way to do it, I'll appreciate any new suggestions.
private void btnEdit_Click(object sender, EventArgs e)
{
RichTextBox rchTemp = new RichTextBox();
foreach (string line in rchCode.Lines)
{
rchTemp.AppendText("\r\n" + line.Trim());
}
RichTextBox rchTemp2 = new RichTextBox();
int indentCount = 0;
bool shouldIndent = false;
foreach (string line in rchTemp.Lines)
{
if (shouldIndent)
indentCount++;
if (line.Contains("}"))
indentCount--;
if (indentCount == 0)
{
rchTemp2.AppendText("\r\n" + line);
shouldIndent = line.Contains("{");
continue;
}
string blankSpace = string.Empty;
for (int i = 0; i < indentCount; i++)
{
blankSpace += " ";
}
rchTemp2.AppendText("\r\n" + blankSpace + line);
shouldIndent = line.Contains("{");
}
rchCode.Text = rchTemp2.Text;
}
public static string FormatCode(string code)
{
var lines = code.Split('\n').Select(s => s.Trim());
var strBuilder = new StringBuilder();
int indentCount = 0;
bool shouldIndent = false;
foreach (string line in lines)
{
if (shouldIndent)
indentCount++;
if (line.Trim() == "}")
indentCount--;
if (indentCount == 0)
{
strBuilder.AppendLine(line);
shouldIndent = line.Contains("{");
continue;
}
string blankSpace = string.Empty;
for (int i = 0; i < indentCount; i++)
{
blankSpace += " ";
}
if (line.Contains("}") && line.Trim() != "}")
indentCount--;
strBuilder.AppendLine(blankSpace + line);
shouldIndent = line.Contains("{");
}
return strBuilder.ToString();
}
Little improvement on answer on top
if line public string Foo { get; set; } correct indent.
I am creating a tool in Visual C#.Net. The algorithm of the tool is to check for all space/s before/after a parenthesis and create an error message for the found errors.
For example: input is ( Text )
Error will be raise because space before and after the parenthesis is detected.
If errors are found the code will add the errors in listview1.items().
To make my question much clearer for you here's my code:
private void button1_Click(object sender, EventArgs e)
{
int error_counter = 0;
listView1.Items.Clear();
//requirement 8c
//check for a space in open and close parenthesis
Regex test = new Regex(#"\(\s.+\s\)|\[\s.+\s\]|\{\s.+\s\}", RegexOptions.IgnoreCase);
MatchCollection matchlist = test.Matches(richTextbox1.Text);
if (matchlist.Count > 0)
{
for (int i = 0; i < matchlist.Count; i++)
{
Match firstMatch = matchlist[i];
string firstMatch_string = firstMatch.ToString();
string[] errors = new string[matchlist.Count];
errors[i] = "Ommit Space between a bracket";
listView1.Items.Add(errors[i]);
error_counter++;
}
}
}
private void listView1_ItemActivate(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
ListViewItem item = listView1.SelectedItems[0];
MessageBox.Show(item.ToString());
}
}
What I looking for is that all of the items of my listview1 will be clickable, and after a click was made by the user the tool will highlight the error found in the richtextbox1.
Thanks for all your help guys!
As someone already told you, use the Index and Length properties of the Match class. Here's a short example implementing a weird textbox selection strategy. But it works effectively demonstrating the concept:
public partial class Form1 : Form
{
List<Error> errors = new List<Error>();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
errors = new List<Error>();
listView1.Items.Clear();
foreach(Match m in Regex.Matches(richTextBox1.Text, #"(\(\s+|\s+\)|\[\s+|\s+\]|\{\s+|\s+\})", RegexOptions.IgnoreCase))
{
//you may decide to differentiate the msg according to the specific problem
Error error = new Error(m, "Ommit Space between a bracket");
this.errors.Add(error);
listView1.Items.Add(error.msg);
}
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedIndices.Count > 0)
{
Error error = errors[listView1.SelectedIndices[0]];
Select(richTextBox1, error);
}
}
private static void Select(RichTextBox rtb, Error e) {
string o = rtb.Text;
rtb.Clear();
for (int i = 0; i < o.Length; i++)
{
if (i >= e.index && i <= e.index + e.length)
{
rtb.SelectionColor = Color.White;
rtb.SelectionBackColor = Color.Red;
}
else
{
rtb.SelectionColor = Color.Black;
rtb.SelectionBackColor = Color.White;
}
rtb.AppendText(o[i].ToString());
}
}
}
public class Error
{
public int index;
public int length;
public string value;
public string msg;
public Error(Match m, string msg)
{
this.index = m.Index;
this.length = m.Length;
this.value = m.Value;
this.msg = msg;
}
}
The Match object (like firstMatch) has two usefull properties here : Index and Length.
They give you the position and the length of the match in question in the original text.
With that in your knowledge, you just have to implement the highlight in the richTextBox !