I have a listview which binds the customer infos. Also, I have a textbox which provides searching in the listview. If the textbox's typed character or symbol matches with a datalist item then it highlights the matched item. Concerning this, I want to count the matched items number. But every search the count is "0". When I debug it then the count is true in the foreach loop but it is always zero in the TxtSearch_PreviewKeyDown. Please have a look. How can I found out the matched item amount?
private int highlightcount;
public int highlightCount
{
get;
set;
}
private void FindListViewItem(DependencyObject obj)
{
try
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
ListViewItem lv = obj as ListViewItem;
if (lv != null)
{
HighlightText(lv);
}
else
FindListViewItem(VisualTreeHelper.GetChild(obj as DependencyObject, i));
}
}
catch
{
MessageBox.Show("Bevor Sie die Suche Stauten, wählen Sie bitte eine Adresse in der linken Spalte aus.");
}
}
/// <summary>
/// Method for highlighting matched listview item
/// </summary>
/// <param name="itx"></param>
public void HighlightText(Object itx)
{
try
{
if (itx != null)
{
if (itx is TextBlock)
{
Regex regex = new Regex("(" + TxtSearch.Text + ")", RegexOptions.IgnoreCase);
TextBlock tb = itx as TextBlock;
if (TxtSearch.Text.Length == 0)
{
string str = tb.Text;
tb.Inlines.Clear();
tb.Inlines.Add(str);
return;
}
string[] substrings = regex.Split(tb.Text);
tb.Inlines.Clear();
highlightCount = 0;
foreach (var item in substrings)
{
if (regex.Match(item).Success)
{
Run runx = new Run(item);
runx.Background = Brushes.Lime;
tb.Inlines.Add(runx);
highlightCount++;
if (tb.IsMouseOver)
{
tb.IsEnabled = false;
}
}
else
{
tb.Inlines.Add(item);
tb.IsEnabled = false;
}
}
return ;
}
else
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(itx as DependencyObject); i++)
{
HighlightText(VisualTreeHelper.GetChild(itx as DependencyObject, i));
}
}
}
}
catch
{
MessageBox.Show("Suche Error");
}
}
private void TxtSearch_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (TxtSearch.Text.Length > 1 && e.Key==Key.Enter)
{
Mouse.OverrideCursor = Cursors.Wait;
ListControl lc = getactivListview();
FindListViewItem(lc);
Mouse.OverrideCursor = null;
MessageBox.Show(highlightCount.ToString());
FocusManager.SetFocusedElement(this, TxtSearch);
}
Try removing highlightCount = 0; from your HighlightText method and add it to the TxtSearch_PreviewKeyDown Eventhandler (over ListControl lc = getactivListview(); or under MessageBox.Show(highlightCount.ToString());)
Related
How do I change the autocomplete on a TextBox? I want that when I type a string, the box suggest items containing that string instead of starting with.
My code is:
class MyClass
{
private AutoCompleteStringCollection autoCompleteList = new AutoCompleteStringCollection();
public MyClass()
{
InitializeComponent();
autoCompleteList.AddRange(ListNames.Select(x=>x.Name).ToArray());
textBoxName.AutoCompleteCustomSource = autoCompleteList;
textBoxName.AutoCompleteSource = AutoCompleteSource.CustomSource;
textBoxName.AutoCompleteMode = AutoCompleteMode.Suggest;
textBoxName.KeyDown += TextBoxtextName_KeyDown;
}
private void TextBoxClient_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Enter)
{
this.Name = (sender as TextBox).Text;
}
}
}
What I want:
Looking at your code you have everything you need but 1 line of code. That line is:
This will only work if the start of a string is entered
//Suggestion only
textBoxName.AutoCompleteMode = AutoCompleteMode.Suggest;
//Suggest and autocomplete
textBoxName.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
This will work as a contains method but works with a custom control
You can also make a custom textbox control that fits your needs.
Custom textbox class:
public class AutoCompleteTextBox : TextBox
{
private ListBox _listBox;
private bool _isAdded;
private String[] _values;
private String _formerValue = String.Empty;
public AutoCompleteTextBox()
{
InitializeComponent();
ResetListBox();
}
private void InitializeComponent()
{
_listBox = new ListBox();
this.KeyDown += this_KeyDown;
this.KeyUp += this_KeyUp;
}
private void ShowListBox()
{
if (!_isAdded)
{
Parent.Controls.Add(_listBox);
_listBox.Left = Left;
_listBox.Top = Top + Height;
_isAdded = true;
}
_listBox.Visible = true;
_listBox.BringToFront();
}
private void ResetListBox()
{
_listBox.Visible = false;
}
private void this_KeyUp(object sender, KeyEventArgs e)
{
UpdateListBox();
}
private void this_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Enter:
case Keys.Tab:
{
if (_listBox.Visible)
{
Text = _listBox.SelectedItem.ToString();
ResetListBox();
_formerValue = Text;
this.Select(this.Text.Length, 0);
e.Handled = true;
}
break;
}
case Keys.Down:
{
if ((_listBox.Visible) && (_listBox.SelectedIndex < _listBox.Items.Count - 1))
_listBox.SelectedIndex++;
e.Handled = true;
break;
}
case Keys.Up:
{
if ((_listBox.Visible) && (_listBox.SelectedIndex > 0))
_listBox.SelectedIndex--;
e.Handled = true;
break;
}
}
}
protected override bool IsInputKey(Keys keyData)
{
switch (keyData)
{
case Keys.Tab:
if (_listBox.Visible)
return true;
else
return false;
default:
return base.IsInputKey(keyData);
}
}
private void UpdateListBox()
{
if (Text == _formerValue)
return;
_formerValue = this.Text;
string word = this.Text;
if (_values != null && word.Length > 0)
{
string[] matches = Array.FindAll(_values,
x => (x.ToLower().Contains(word.ToLower())));
if (matches.Length > 0)
{
ShowListBox();
_listBox.BeginUpdate();
_listBox.Items.Clear();
Array.ForEach(matches, x => _listBox.Items.Add(x));
_listBox.SelectedIndex = 0;
_listBox.Height = 0;
_listBox.Width = 0;
Focus();
using (Graphics graphics = _listBox.CreateGraphics())
{
for (int i = 0; i < _listBox.Items.Count; i++)
{
if (i < 20)
_listBox.Height += _listBox.GetItemHeight(i);
// it item width is larger than the current one
// set it to the new max item width
// GetItemRectangle does not work for me
// we add a little extra space by using '_'
int itemWidth = (int)graphics.MeasureString(((string)_listBox.Items[i]) + "_", _listBox.Font).Width;
_listBox.Width = (_listBox.Width < itemWidth) ? itemWidth : this.Width; ;
}
}
_listBox.EndUpdate();
}
else
{
ResetListBox();
}
}
else
{
ResetListBox();
}
}
public String[] Values
{
get
{
return _values;
}
set
{
_values = value;
}
}
public List<String> SelectedValues
{
get
{
String[] result = Text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
return new List<String>(result);
}
}
}
Usage:
string[] nameArray = { "name1", "name2", "name3", "bla name" };
AutoCompleteTextBox tb = new AutoCompleteTextBox();
tb.Values = nameArray;
tb.Location = new Point(10,10);
tb.Size = new Size(25,75);
this.Controls.Add( tb );
I got the code for the custom control from: SO Question - Autocomplete contains
I have a program where i need to count how many females and Males are in the file that has been read into the richtextbox, but I'm not sure how to do that , in the file has the name, gender,specific job . I have to count between 15 different people
for example : " Donna,Female,Human Resources.",
This is what I have so far:
private void Form1_Load(object sender, EventArgs e)
{
StreamReader sr;
richTextBox1.Clear();
sr = new StreamReader("MOCK_DATA.txt");
string data;
while (!sr.EndOfStream)
{
data = sr.ReadLine();
richTextBox1.AppendText(data + "\n");
}
}
private void button1_Click(object sender, EventArgs e)
{
string[] data = richTextBox1.Text.Split(',');
for (int n = 0; n < data.Length; n++)
{
if (data[n] == richTextBox1.Text)
n++;
To get the plain text from a RichTextBox (stolen from this article):
string StringFromRichTextBox(RichTextBox rtb)
{
TextRange textRange = new TextRange(
// TextPointer to the start of content in the RichTextBox.
rtb.Document.ContentStart,
// TextPointer to the end of content in the RichTextBox.
rtb.Document.ContentEnd
);
// The Text property on a TextRange object returns a string
// representing the plain text content of the TextRange.
return textRange.Text;
}
Basic word counting routine:
int CountWord(string textToSearch, string word)
{
int count = 0;
int i = textToSearch.IndexOf(word);
while (i != -1)
{
count++;
i = textToSearch.IndexOf(word, i+1);
}
return count;
}
Putting it together:
var plainText = StringFromRichTextBox(richTextBox1);
var countOfMale = CountWord(plainText, "Male");
var countOfFemale = CountWord(plainText, "Female");
private void toolStripButton81_Click(object sender, EventArgs e)
{
string findterm = string.Empty;
findterm = toolStripTextBox2.Text;
// the search term - specific word
int loopCount = 0;
// count the number of instance
int findPos = 0;
// depending on checkbox settings
// whole word search or match case etc
try
{
while (findPos < GetRichTextBox().Text.Length)
{
if (wholeWordToolStripMenuItem.CheckState == CheckState.Checked & matchCaseToolStripMenuItem.CheckState == CheckState.Checked)
{
findPos = GetRichTextBox().Find(findterm, findPos, RichTextBoxFinds.WholeWord | RichTextBoxFinds.MatchCase);
}
else if (wholeWordToolStripMenuItem.CheckState == CheckState.Checked)
{
findPos = GetRichTextBox().Find(findterm, findPos, RichTextBoxFinds.WholeWord);
}
else if (matchCaseToolStripMenuItem.CheckState == CheckState.Checked)
{
findPos = GetRichTextBox().Find(findterm, findPos, RichTextBoxFinds.MatchCase);
}
else
{
findPos = GetRichTextBox().Find(findterm, findPos, RichTextBoxFinds.None);
}
GetRichTextBox().Select(findPos, toolStripTextBox2.Text.Length);
findPos += toolStripTextBox2.Text.Length + 1;
loopCount = loopCount + 1;
}
}
catch
{
findPos = 0;
}
// at the end bring the cursor at the beginning of the document
GetRichTextBox().SelectionStart = 0;
GetRichTextBox().SelectionLength = 0;
GetRichTextBox().ScrollToCaret();
// Show the output in statusbar
toolStripStatusLabel2.Text = "Instances: " + loopCount.ToString();
}
I want to add item into the listview, the problem I'm facing is that when I add an item that I type in on the text box. It is able to insert the value in the listview column that I want. But when it update, all the data that it loaded from the textfile is missing. Only the value that I type in is left.
Before add data:
http://www.hostpic.org/images/1508121529460086.png
After insert the data:
http://www.hostpic.org/images/1508121531010086.png
private void button2_Click(object sender, EventArgs e)
{
//add button
string s;
listView1.Items.Clear();
listView1.BeginUpdate();
for (int i = 0; i < comboBox1.Items.Count; i++)
{
if ((comboBox1.SelectedIndex + 1) + "" == proDetail[i].id)
{
//proDetail[i].estimation = double.Parse(textBox3.Text);
proDetail[i].estimation = textBox3.Text;
s = textBox4.Text;
proDetail[i].pre = s.Split(',');
}
}
for (int j = 0; j < comboBox1.Items.Count; j++)
{
if (proDetail[j].pre != null)
{
project = listView1.Items.Add(proDetail[j].id);
project.SubItems.Add(proDetail[j].activity);
if (proDetail[j].pre.Length <= 1)
{
foreach (string words in proDetail[j].pre)
{
preValue = words;
}
}
else
{
preValue = string.Empty;
foreach (string words in proDetail[j].pre)
{
preValue += words + ",";
}
}
project.SubItems.Add(proDetail[j].estimation.ToString());
project.SubItems.Add(preValue);
}
else
{
project = listView1.Items.Add(proDetail[j].id);
project.SubItems.Add(proDetail[j].activity);
}
listView1.EndUpdate();
listView1.Refresh();
}
}
I forgot to include the
project.SubItems.Add(proDetail[j].estimation);
in the else statement.
Thanks for the help.
This is the culprit:
listView1.Items.Clear();
That has removed all existing items from the control.
I have a listview which binds the customers informations. I highlight the listview items by typing in a textbox. For example, when I type "PET" into the textbox then it highlights the "PET"s in the listview items. It works and highlights.
But after that when I click on the highlighted item it gives an error. But it is interesting when I click on a free place in the listview item it works. For example, it highlighted PETER HEINZ. IF I click on to PETER or HEINZ it gives error. But, if I click on the space between PETER HEINZ it works. What a error is this? The error message is
System.InvalidOperationException was unhandled
Message="'System.Windows.Documents.Run' is not a Visual or Visual3D."
The source code is below:
private void HighlightText(Object itx)
{
if (itx != null)
{
if (itx is TextBlock)
{
Regex regex = new Regex("(" + textBox1.Text + ")", RegexOptions.IgnoreCase);
TextBlock tb = itx as TextBlock;
if (textBox1.Text.Length == 0)
{
string str = tb.Text;
tb.Inlines.Clear();
tb.Inlines.Add(str);
return;
}
string[] substrings = regex.Split(tb.Text);
tb.Inlines.Clear();
foreach (var item in substrings)
{
if (regex.Match(item).Success)
{
Run runx = new Run(item);
runx.Background = Brushes.LightGray;
tb.Inlines.Add(runx);
}
else
{
tb.Inlines.Add(item);
}
}
return;
}
else
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(itx as DependencyObject); i++)
{
HighlightText(VisualTreeHelper.GetChild(itx as DependencyObject, i));
}
}
}
}
Here's a revisement. Can you paste it over yours and see if it works better in your application?
key points:
Added protection to not let non-visual objects make it to the GetChild recursion
Added check for textbox1 being empty
trivial: moved tb.inlines.clear to reduce code repitition
trivial: inverted itx null check to reduce nesting
.
private void HighlightText(Object itx)
{
//safety checks
if (itx == null)
return;
if (String.isNullOrEmpty(textBox1.Text)
return; //just in case the box is empty
if (! (itx is Visual || itx is System.Windows.Media.Media3D.Visual3D)
return; //prevent from getting children on non-visual element
if (itx is TextBlock)
{
Regex regex = new Regex("(" + textBox1.Text + ")", RegexOptions.IgnoreCase);
TextBlock tb = itx as TextBlock;
tb.Inlines.Clear();
if (textBox1.Text.Length == 0)
{
string str = tb.Text;
tb.Inlines.Add(str);
return;
}
string[] substrings = regex.Split(tb.Text);
foreach (var item in substrings)
{
if (!regex.Match(item).Success)
{
Run runx = new Run(item);
runx.Background = Brushes.LightGray;
tb.Inlines.Add(runx);
}
else
{
tb.Inlines.Add(item);
}
}
return;
}
else
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(itx as DependencyObject); i++)
{
HighlightText(VisualTreeHelper.GetChild(itx as DependencyObject, i));
}
}
}
I have a tabcontrol in my application. I have a listbox which contains the line no of error and file name and path of the file.On double click i want to add the new tab page.The title of the tabpage should be the name of file from the listbox. If the tabpage with the particular filename already exists then it should not open new tabpage the cursor should point to that page. How to retreive the name of the tabpages .
private void lstErrorList_MouseDoubleClick(object sender, MouseEventArgs e)
{
ArrayList errorType = new ArrayList();
if (lstErrorList.Items.Count > 0)
{
string error = lstErrorList.SelectedItem.ToString();
{
int result = error.LastIndexOf('\\');
string filename = error.Substring(result + 1, error.Length - (result + 1));
int pagecount;
TabPage tp = new TabPage();
pagecount = this.tabControl1.TabPages.Count;
for(int tbpagecount=0;tbpagecount<pagecount;tbpagecount++)
{
pagelist.Add(this.tabControl1.TabPages.ToString());
}
if (pagelist.Contains(filename))
{
}
else
{
this.tabControl1.TabPages.Insert(pagecount, filename);
pagecount++;
}
if (fileNamesList.Count == 0)
fileNamesList.Add(filename);
else
{
if (fileNamesList.Contains(filename))
{
//fileNamesList.Add("");
}
else
{
fileNamesList.Add(filename);
}
}
}
bool found = false;
foreach (TabPage tab in tabControl1.TabPages) {
if (filename.Equals(tab.Name)) {
tabControl1.SelectedTab = tab;
found = true;
}
}
if( ! found)
tabControl1.TabPages.Add(filename,filename);
var tabPage = tabControl1.TabPages[filename];
if (tabPage != null)
{
tabControl1.SelectedTab = tabPage;
}
else
{
tabControl1.TabPages.Add(filename, filename);
}
What about something like this?
string fileName = "";
bool isPresent = false;
for (int i = 0; i < tabControl1.TabPages.Count; i++)
{
if (tabControl1.TabPages[i].Name == filename)
{
isPresent = true;
break;
}
}
if (isPresent)
{
tabControl1.TabPages.Add(filename);
}
else
{
tabControl1.SelectTab(tab.TabIndex);
}