retrieving an item in a listview - c#

I'm using ListView.GetItemAt(x,y) to retrieve an item from the ListView, but I'm not
able to get the item when I set the FullRowSelect option to false.
I'm not sure of how to do it in .NET 1.1. Does anyone have any pointers?
Here's a code snippet:
public int GetListViewSubItem(ListView listView1, Point pt)
{
const int LVM_FIRST = 0x1000;
const int LVM_GETSUBITEMRECT = (LVM_FIRST + 56);
const int LVIR_BOUNDS = 0;
RECT myrect;
ListViewItem lvitem = listView1.GetItemAt(pt.X, pt.Y);
if(lvitem == null && listView1.SelectedItems.Count > 0)
lvitem = listView1.SelectedItems[0];
int intLVSubItemIndex = -1;
ListViewItem.ListViewSubItem LVSubItem = null;
if(lvitem != null)
{
int intSendMessage;
for ( int i = 1; i <= lvitem.SubItems.Count - 1; i++)
{
LVSubItem = lvitem.SubItems[i];
myrect = new RECT();
myrect.top = i;
myrect.left = LVIR_BOUNDS;
intSendMessage = SendMessage(listView1.Handle,
LVM_GETSUBITEMRECT,
lvitem.Index, ref myrect);
if (pt.X < myrect.left)
{
LVSubItem = lvitem.SubItems[0];
intLVSubItemIndex = 0;
break;
}
else if (pt.X >= myrect.left & pt.X <= myrect.right)
{
intLVSubItemIndex = i;
break;
}
else
LVSubItem = null;
}
}
if (LVSubItem == null || lvitem == null)
{
intLVSubItemIndex = -1;
}
return intLVSubItemIndex;
}
This method is supposed to show me which cell was clicked.
Tt works, but if I change the fullrowselect to false, it returns a null value.
I even tried getitemat(0,e.y), but it didn't work.
whenever I select an item in the ListView, it highlighted with the color blue, so it is not possible to view what is selected. I'm trying to remove that blue highlight.
Any thoughts?

Can you elaborate a bit on what you're trying to do?
Is your ListView's ViewStyle set to Details? Since you mention setting FullRowSelect to false I assume it is.
GetItemAt(x, y) will only work if the mouse was clicked on actual text that belongs to an item. So if you've clicked on the same row as an item but in a column that it doesn't have text for, it'll return null.
A workaround for this is to simply pass 0 in as the x parameter:
private void listView1_MouseUp(object sender, MouseEventArgs e)
{
ListViewItem item = listView1.GetItemAt(0, e.Y);
if (item == null)
{
MessageBox.Show("Null");
}
else
{
MessageBox.Show(item.Text);
}
}
I can confirm that this works fine - it returns the item that lives on that row even if only the first column has text in it.

private int getSelectedSubItemIndex(ListView listView)
{
if (listView.SelectedItems.Count == 1)
{
int x = 0;
ListViewItem item = listView.SelectedItems[0];
Point pt = listView.PointToClient(Control.MousePosition);
for (int idx = 0; idx < item.SubItems.Count; ++idx)
{
x += listView.Columns[idx].Width;
if (pt.X < x)
return idx;
}
}
return -1;
}

private void listView1_MouseClick(object sender, MouseEventArgs e)
{
int column = 0;
ListViewItem item = listView1.GetItemAt(e.X, e.Y);
for (column = 0; column < item.SubItems.Count; column++)
{
if (item.SubItems[column].Bounds.X > e.X) break;
}
if (item != null)
{
textBox1.Text = item.SubItems[column-1].Text;
}
}

Related

How To Find All Matches In Rich Text Box? [duplicate]

In my RichtextBox, if I have written as below.
This is my pen,
his pen is beautiful.
Now I search word "is" then
output would be as below.
All "is" should be highlighted.
What about:
static class Utility {
public static void HighlightText(this RichTextBox myRtb, string word, Color color) {
if (word == string.Empty)
return;
int s_start = myRtb.SelectionStart, startIndex = 0, index;
while((index = myRtb.Text.IndexOf(word, startIndex)) != -1) {
myRtb.Select(index, word.Length);
myRtb.SelectionColor = color;
startIndex = index + word.Length;
}
myRtb.SelectionStart = s_start;
myRtb.SelectionLength = 0;
myRtb.SelectionColor = Color.Black;
}
}
Looks like this would do it.
http://www.dotnetcurry.com/ShowArticle.aspx?ID=146
int start = 0;
int indexOfSearchText = 0;
private void btnFind_Click(object sender, EventArgs e)
{
int startindex = 0;
if(txtSearch.Text.Length > 0)
startindex = FindMyText(txtSearch.Text.Trim(), start, rtb.Text.Length);
// If string was found in the RichTextBox, highlight it
if (startindex >= 0)
{
// Set the highlight color as red
rtb.SelectionColor = Color.Red;
// Find the end index. End Index = number of characters in textbox
int endindex = txtSearch.Text.Length;
// Highlight the search string
rtb.Select(startindex, endindex);
// mark the start position after the position of
// last search string
start = startindex + endindex;
}
}
public int FindMyText(string txtToSearch, int searchStart, int searchEnd)
{
// Unselect the previously searched string
if (searchStart > 0 && searchEnd > 0 && indexOfSearchText >= 0)
{
rtb.Undo();
}
// Set the return value to -1 by default.
int retVal = -1;
// A valid starting index should be specified.
// if indexOfSearchText = -1, the end of search
if (searchStart >= 0 && indexOfSearchText >=0)
{
// A valid ending index
if (searchEnd > searchStart || searchEnd == -1)
{
// Find the position of search string in RichTextBox
indexOfSearchText = rtb.Find(txtToSearch, searchStart, searchEnd, RichTextBoxFinds.None);
// Determine whether the text was found in richTextBox1.
if (indexOfSearchText != -1)
{
// Return the index to the specified search text.
retVal = indexOfSearchText;
}
}
}
return retVal;
}
// Reset the richtextbox when user changes the search string
private void textBox1_TextChanged(object sender, EventArgs e)
{
start = 0;
indexOfSearchText = 0;
}
This will show all the searched criteria at the same time.
Using: 1 Textbox (to enter the text to search for) and 1 Button (to Run the Search).
Enter your search criteria inside the textbox and press search button.
// On Search Button Click: RichTextBox ("rtb") will display all the words inside the document
private void btn_Search_Click(object sender, EventArgs e)
{
try
{
if (rtb.Text != string.Empty)
{// if the ritchtextbox is not empty; highlight the search criteria
int index = 0;
String temp = rtb.Text;
rtb.Text = "";
rtb.Text = temp;
while (index < rtb.Text.LastIndexOf(txt_Search.Text))
{
rtb.Find(txt_Search.Text, index, rtb.TextLength, RichTextBoxFinds.None);
rtb.SelectionBackColor = Color.Yellow;
index = rtb.Text.IndexOf(txt_Search.Text, index) + 1;
rtb.Select();
}
}
}
catch (Exception ex) { MessageBox.Show(ex.Message, "Error"); }
}
}
}
If you only want to match the whole word you can use this, note that this ignores case and also the |s\b means that plurals get highlighted e.g. Cat matches cats but not caterpiller :
public static void HighlightText(RichTextBox myRtb, string word, Color color)
{
if (word == string.Empty)
return;
var reg = new Regex(#"\b" + word + #"(\b|s\b)",RegexOptions.IgnoreCase);
foreach (Match match in reg.Matches(myRtb.Text))
{
myRtb.Select(match.Index, match.Length);
myRtb.SelectionColor = color;
}
myRtb.SelectionLength = 0;
myRtb.SelectionColor = Color.Black;
}
private void button3_Click(object sender, EventArgs e)
{
if (textBox1.Text != "")
{
for (int i = 0; i < richTextBox1.TextLength; i++)
{
richTextBox1.Find(textBox1.Text, i, RichTextBoxFinds.None);
richTextBox1.SelectionBackColor = Color.Red;
}
}
else
{
for (int i = 0; i < richTextBox1.TextLength; i++)
{
richTextBox1.SelectAll();
richTextBox1.SelectionBackColor = Color.White;
}
}
}[lets make it!][1]
I would do it like that because all the other answers highlight the text, but doesnt change it back after you searched again.
Use the RichText Find Method to find the starting index for the searching word.
public int FindMyText(string searchText, int searchStart, int searchEnd)
{
int returnValue = -1;
if (searchText.Length > 0 && searchStart >= 0)
{
if (searchEnd > searchStart || searchEnd == -1)
{
int indexToText = richTextBox1.Find(searchText, searchStart, searchEnd, RichTextBoxFinds.MatchCase);
if (indexToText >= 0)
{
returnValue = indexToText;
}
}
}
return returnValue;
}
Use a Button or TextChangeListener and Search for your word.
private void button1_Click(object sender, EventArgs e)
{
// Select the first char in your Richtextbox
richTextBox1.SelectionStart = 0;
richTextBox1.SelectionLength = richTextBox1.TextLength;
// Select until the end
richTextBox1.SelectionColor = Color.Black;
// Make the Text Color black
//Use an Inputfield to add the searching word
var word = txtSearch.Text;
//verify the minimum length otherwise it may freeze if you dont have text inside
if (word.Length > 3)
{
int s_start = richTextBox1.SelectionStart, startIndex = 0, index;
while ((index = FindMyText(word, startIndex, richTextBox1.TextLength)) != -1)
{
// goes through all possible found words and color them blue (starting index to end)
richTextBox1.Select(index, word.Length);
richTextBox1.SelectionColor = Color.Blue;
startIndex = index + word.Length;
}
// Color everything between in color black to highlight only found words
richTextBox1.SelectionStart = startIndex;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectionColor = Color.Black;
}
}
I would highly recommend to set a minimum word length to avoid freezing and high memory allocation.

Show recursive row count in Devexpress XtraGrid GroupRow

I have a gridview with multiple groups and I use the CustomDrawGroupRow Event to display the row count for each group:
private void gridView_CustomDrawGroupRow(object sender, DevExpress.XtraGrid.Views.Base.RowObjectCustomDrawEventArgs e)
{
var view = (GridView)sender;
var info = (GridGroupRowInfo)e.Info;
var caption = info.Column.Caption;
if (info.Column.Caption == string.Empty)
{
caption = info.Column.ToString();
}
info.GroupText = $"{caption} : {info.GroupValueText} ({view.GetChildRowCount(e.RowHandle)})";
}
Now I would like to display the row count recursively, so that the first level shows a count of 2171 (1913 + 135 + 123).
This is what I have tried, but it throws a StackOverflowException and I cannot see the problem here:
private void gridView_CustomDrawGroupRow(object sender, DevExpress.XtraGrid.Views.Base.RowObjectCustomDrawEventArgs e)
{
var view = (GridView)sender;
var info = (GridGroupRowInfo)e.Info;
var caption = info.Column.Caption;
if (info.Column.Caption == string.Empty)
{
caption = info.Column.ToString();
}
info.GroupText = $"{caption} : {info.GroupValueText} ({GetRowCountRecursive(view, e.RowHandle)})";
}
private int GetRowCountRecursive(GridView view, int rowHandle)
{
int totalCount = 0;
int childrenCount = view.GetChildRowCount(rowHandle);
for (int i = 0; i < childrenCount; i++)
{
var childRowHandle = view.GetChildRowHandle(rowHandle, i);
totalCount += GetRowCountRecursive(view, childRowHandle);
}
return totalCount;
}
I was missing to check if childRowHandle is a group row with IsGroupRow(). If not, the recursion have to stop and totalCount need to be increased by 1.
private int GetRowCountRecursive(GridView view, int rowHandle)
{
int totalCount = 0;
int childrenCount = view.GetChildRowCount(rowHandle);
for (int i = 0; i < childrenCount; i++)
{
var childRowHandle = view.GetChildRowHandle(rowHandle, i);
if (view.IsGroupRow(childRowHandle))
{
totalCount += GetRowCountRecursive(view, childRowHandle);
}
else
{
totalCount++;
}
}
return totalCount;
}
You can use GroupRowInfo.ChildControllerRowCount property to get the row count. The instance of GroupRowInfo class you can get from GridGroupRowInfo.RowKey property.
Here is example:
private void gridView1_CustomDrawGroupRow(object sender, RowObjectCustomDrawEventArgs e)
{
var view = (GridView)sender;
var info = (GridGroupRowInfo)e.Info;
var caption = info.Column.Caption;
if (info.Column.Caption == string.Empty)
{
caption = info.Column.ToString();
}
var groupInfo = info.RowKey as GroupRowInfo;
info.GroupText = $"{caption} : {info.GroupValueText} ({groupInfo?.ChildControllerRowCount})";
}
Here is the screenshot:

Save and Restore Row Selections in a DataGrid

The problem is fairly straightforward. My datagrid is filled from my ItemSource (bindingList) which is basically a list of objects filled with strings.
In this certain part of my code I need to update my bindingList.
Unfortunately when it is updated all user row selections made in the DataGrid dissappear.
This is an inconvenience to the user that I would like to remedy. So that when the user clicks the button that results in the bindingList to update, the selections are saved in case the user wants to make further changes.
Code Right Now:
//Save DataGrid Row Selections
bindingList[1] = (new ItemClass() { columnnumber = colonum, xcoord = xpos, ycoord = ypos, description = descrip });
dataGrid.ItemSource = bindingList;
//Restore DataGrid Row Selections
EDIT:
Wider scope as requested:
private void Y_Incre_Button_Click(object sender, RoutedEventArgs e)
{
if (dataGrid.SelectedItems.Count != 0)
{
string colonum;
string xpos;
string ypos;
string descrip;
for (int i = 0; i < bindingList.Count; i++)
{
int selectionIndex = dataGrid.SelectedIndex;
if (selectionIndex > -1)
{
var curItem = bindingList[selectionIndex];
int yNum = int.Parse(curItem.ycoord);
int yNum2 = (yNum + 10);
colonum = curItem.columnnumber;
xpos = curItem.xcoord;
ypos = yNum2.ToString();
descrip = curItem.description;
//Save DataGrid Row Selections
bindingList[selectionIndex] = (new ItemClass() { columnnumber = colonum, xcoord = xpos, ycoord = ypos, description = descrip });
//Restore DataGrid Row Selections
}
}
}
else
{
MessageBox.Show("No Rows Selected");
}
}
To get this working store the row indices of the selected items before they are replaced, and then reselect those records after the "replace" operation is complete. Also, have a look at this example.
private void Y_Incre_Button_Click(object sender, RoutedEventArgs e)
{
if (dataGrid.SelectedItems.Count != 0)
{
// Save DataGrid Row Selections
List<int> selectedRowIndexList = new List<int>();
foreach (object item in dataGrid.SelectedItems)
{
selectedRowIndexList.Add(dataGrid.Items.IndexOf(item));
}
for (int i = 0; i < bindingList.Count; i++)
{
int selectionIndex = dataGrid.SelectedIndex;
if (selectionIndex > -1)
{
ItemClass curItem = bindingList[selectionIndex];
int yNum = int.Parse(curItem.ycoord);
int yNum2 = yNum + 10;
string colonum = curItem.columnnumber;
string xpos = curItem.xcoord;
string ypos = yNum2.ToString();
string descrip = curItem.description;
bindingList[selectionIndex] = new ItemClass { columnnumber = colonum, xcoord = xpos, ycoord = ypos, description = descrip };
}
}
// Restore DataGrid Row Selections
dataGrid.SelectedItems.Clear();
foreach (int rowIndex in selectedRowIndexList)
{
if (rowIndex < 0 || rowIndex > dataGrid.Items.Count - 1)
throw new ArgumentException(string.Format("{0} is an invalid row index.", rowIndex));
object item = dataGrid.Items[rowIndex];
dataGrid.SelectedItems.Add(item);
}
}
else
{
MessageBox.Show("No Rows Selected");
}
}

Fill Data in Listbox with another Listbox which is having Data-Bound

I have this two list-box In that first list-box is fill on Combo-box Selected index changed, so List-box 1 is Bounded. Now when I press the > button all selected item in List-box 1 is display in List-box 2.
But instead of Names, I get System.Data.DataRowView
so my question is I want Names instead of this System.Data.DataRowView
my code is this
private void btnSelect1ItemFrom_Click(object sender, EventArgs e)
{
if (listBoxSelectToLedger.Items.Count > 0)
{
for (int i = 0; listBoxSelectToLedger.Items.Count > i; )
{
listBoxSelectToLedger.Items.Remove(listBoxSelectToLedger.Items[i].ToString());
}
}
if (listBoxSelectFromLedger.SelectedItem != null)
{
** for (int i = 0; i < listBoxSelectFromLedger.SelectedItems.Count; i++)
{
listBoxSelectToLedger.Items.Add(listBoxSelectFromLedger.SelectedItems[i].ToString());
} **
}
else
{
MessageBox.Show("No item Selected");
}
* I think I am some where Wrong in Second IF Condition in my Code *
Plz Help me
Thanks in Advance
Try this...
private void button1_Click(object sender, EventArgs e)
{
if(listBoxFrom.SelectedItems.Count>0)
{
for (int x = listBoxFrom.SelectedIndices.Count - 1; x >= 0; x--)
{
int idx = listBoxFrom.SelectedIndices[x];
listBoxTo.Items.Add(listBoxFrom.Items[idx]);
listBoxFrom.Items.RemoveAt(idx);
}
}
}
Hiii.. Deep, use the below code to add ListItem.
foreach (ListItem LI in listBoxFrom.Items)
{
if (LI.Selected)
listBoxTo.Items.Add(LI);
}
To add in to 2nd listbox and remove that from the first listbox you can use below code:
int[] indices = listBoxFrom.GetSelectedIndices();
for (int i = indices.Length - 1; i >= 0; i--)
{
ListItem LI = listBoxFrom.Items[indices[i]];
listBoxTo.Items.Add(LI);
listBoxFrom.Items.RemoveAt(indices[i]);
}
put your No items selected message where you require.
I got answer of my own question.
i have to set my DataRowView object
if (listBoxSelectToLedger.Items.Count > 0)
{
for (int i = 0; listBoxSelectToLedger.Items.Count > i; i = 0)
{
listBoxSelectToLedger.Items.Remove(listBoxSelectToLedger.Items[i].ToString());
}
}
if (listBoxSelectFromLedger.SelectedItem != null)
{
foreach (DataRowView objDataRowView in listBoxSelectFromLedger.SelectedItems)
{
listBoxSelectToLedger.Items.Add(objDataRowView["item_name"].ToString());
}
}
else
{
MessageBox.Show("No Item selected");
}

Clear contents of specific listview columns?

This is how I currently add info to my listview:
private void toolStripMenuItem2_Click(object sender, EventArgs e)
{
int totItems = Seq3.Count - 1;
if (PercentPopTolerance1.Count - 1 > totItems) totItems = PercentPopTolerance1.Count - 1;
for (int i = 0; i <= totItems; i++)
{
ListViewItem lvi = new ListViewItem();
string item1 = "";
string item2 = "";
if (Seq3.Count - 1 >= i) item1 = Seq3[i].ToString();
if (PercentPopTolerance1.Count - 1 >= i) item2 = PercentPopTolerance1[i].ToString();
lvi.SubItems.Add(item1);
lvi.SubItems.Add(item2);
listView2.Items.Add(lvi);
}
}
View of empty listview:
Now how would I clear the contents of any particular column? Say I want to add to column YYMM but before I do this, I want to clear that particular column. How would this be done?
You can clear column values like this
var items = listView1.Items;
foreach (ListViewItem item in items)
{
a.SubItems["YYWW"].Text = "";
}
You should specify a column by its name (a column corresponds to a subitem in a ListViewItem), note that this Name is not ColumnHeader.Name, I mean the corresponding ListViewSubItem.Name:
public void ClearColumn(string colName){
foreach(ListViewItem item in listView1.Items){
var cell = item.SubItems[colName];
if(cell != null) cell.Text = "";
}
}
The following code will work for ColumnHeader.Name passed in instead of ListViewSubItem.Name as the code above does:
public void ClearColumn(string columnHeaderName){
int i = listView1.Columns.IndexOfKey(columnHeaderName);
if(i == -1) return;
foreach(ListViewItem item in listView1.Items){
item.SubItems[i].Text = "";
}
}
You can try the following code to make it work for Text instead of Name:
public void ClearColumn(string colText){
if(listView1.Items.Count == 0) return;
var col = listView1.Columns.Cast<ColumnHeader>()
.Select((x,i)=>new{x,i})
.FirstOrDefault(a=>a.x.Text == colText);
if(col == null) return;
foreach(ListViewItem item in listView1.Items){
item.SubItems[col.i].Text = "";
}
}

Categories

Resources