As an attempt to color text in ListBox i found this guide C# : change listbox items color (i am using windows forms application on visual studio 2012).
The code is working but the problem is that i want to use the textbox in a Right to Left mode, but when i change it in the ListBox settings it does not work, so i assume that it needs to be changed in the code somehow, this is what i need your help for.
Thank you very much!
Alon
Your y position is 0, so everytime you insert a message it's on the left side.
To put it on the right side you have recalculate the postion.
Look at the following example.
private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
MyListBoxItem item = listBox1.Items[e.Index] as MyListBoxItem; // Get the current item and cast it to MyListBoxItem
if (item != null)
{
e.Graphics.DrawString( // Draw the appropriate text in the ListBox
item.Message, // The message linked to the item
listBox1.Font, // Take the font from the listbox
new SolidBrush(item.ItemColor), // Set the color
width - 4, // X pixel coordinate
e.Index * listBox1.ItemHeight,
new StringFormat(StringFormatFlags.DirectionRightToLeft)); // Y pixel coordinate. Multiply the index by the ItemHeight defined in the listbox.
}
else
{
// The item isn't a MyListBoxItem, do something about it
}
}
A list box is natively left-justified and you cannot change this in the UIR editor. You can apply the appropriate justification elements while creating the string to pass to the list box: see the online help for Item Label parameter of the InsertListItem function. All escape codes are to be applied to every line that you insert into the list box; there is no way to apply a default formatting style to the control.
Related
How do I make bold a variable amount of items in a listbox? I've seen solutions like this one, but it appears to only work if I know exactly which items should be bold before runtime. Here's my specific case:
I have a listbox with a list of strings read from a file. I have a search bar that, when typed in, will automatically move items matching that string to the top of the listbox. Unfortunately, being at the top isn't enough of an indicator of "search result," so I also want to make those items bold. Before runtime, I do know all the items I want to be bold will be at the top of the list, but I have no idea how many items that will be. Additionally, when the user erases the search bar's contents, the list will be reordered to its initial order and the bold items should be made not bold.
How do I go back and forth between bold/not bold for specific listbox items at runtime?
Here is my code for the search and display functionality:
private void txtSearch_TextChanged(object sender, EventArgs e)
{
string searchTerm = txtSearch.Text.Trim();
if(searchTerm.Trim() == "") // If the search box is blank, just repopulate the list box with everything
{
listBoxAllTags.DataSource = fullTagList;
return;
}
searchedTagList = new List<UmfTag>();
foreach(UmfTag tag in fullTagList)
{
if(tag.ToString().ToLower().Contains(searchTerm.ToLower()))
{
searchedTagList.Add(tag);
}
}
// Reorder the list box to put the searched tags on top. To do this, we'll create two lists:
// one with the searched for tags and one without. Then we'll add the two lists together.
List<UmfTag> tempList = new List<UmfTag>(searchedTagList);
tempList.AddRange(fullTagList.Except(searchedTagList));
listBoxAllTags.DataSource = new List<UmfTag>(tempList);
}
I was able to solve my own problem. I indeed used the solution present in this question, but I altered it like so:
private void listBoxAllTags_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
FontStyle fontStyle = FontStyle.Regular;
if(e.Index < searchedTagList.Count)
{
fontStyle = FontStyle.Bold;
}
if(listBoxAllTags.Items.Count > 0) // Without this, I receive errors
{
e.Graphics.DrawString(listBoxAllTags.Items[e.Index].ToString(), new Font("Arial", 8, fontStyle), Brushes.Black, e.Bounds);
}
e.DrawFocusRectangle();
}
The second if statement (checking if the count is greater than 0) is required. Without it, I received "index[-1]" errors because my program first starts with empty listboxes, and the DrawString method couldn't draw the string for the empty listBox.Items[] array.
The goal is to add a column of paragraph numbers to a RichTextBox (the numbers show the index of paragraphs in that richtextbox.Document.Blocks). Currently, I use this block of code in LayoutUpdated event of the RichTextBox:
bool _added=false
void onLayoutUpdated(object sender, EventArgs e)
{
if (!_added)
{
_added= true;
scv = Helper.GetFind.FindChild<ScrollViewer>(this, null);
if (scv != null)
{
FrameworkElement documentView = scv.Content as FrameworkElement;
scv.ClearValue(ScrollViewer.ContentProperty);
Grid grid= new Grid();
... I will talk about what I have added here...
scv.Content = grid;
UpdateLayout();
}
}
}
In the grid, I add two columns, the first one is a StackPanel and the second one is the documentView. For each paragraph I add a TextBlock to the StackPanel.Children and I set the height of each textBlock by using Paragraph.ElementStart.GetCharacterRect(LogicalDirection.Forward) methods and the Top & Bottom Properties of the returned Rect(s).
Everything is fine and when there are less than 500 paragraphs, the numbering updates quickly, But as the text gets larger, it gets slower. How can I make it more efficient? Should I use a Canvas instead of a StackPanel? Or is there any better way of doing this?
Thanks.
ListView GridView. Support virtualiztion. I use textblock for each line in some very large document and works great.
I used the procedure I mensioned in the question and then Dispacher.BeginInvoke(...) method. I set DispatcherPriority to ApplicationIdle. I call it when Width chaneges or new Paragraph is added. Sth like this:
_updateIfWidthChangedDispacherO= _ownerTextBox.Dispatcher.BeginInvoke((Action)(() =>
{
updateIfWidthChanged();
}),
DispatcherPriority.ApplicationIdle);
I am looking for a solution to add an Item in a ListBoxControl with different colors in the same Row
ex: 'imported company [ XCompany ]' - i need 'imported company' with a gray color and the rest with black
also i need in case I have errors (Red)
I can't find (if exists) the method to add an Html text
Thanks
You can activate the HTML Text Formatting feature within the ListBoxControl via the ListBoxControl.AllowHtmlDraw property:
listBoxControl.AllowHtmlDraw = DevExpress.Utils.DefaultBoolean.True;
listBoxControl.Items.AddRange(new object[] {
"Color <color=Red>Red</color>",
"Color <color=Green>Green</color>",
"Color <color=Blue>Blue</color>"
});
Another way to do that is implementing the DrawItem event of the ListBox with a method like :
internal static void DrawListBox(object sender, DevExpress.XtraEditors.ListBoxDrawItemEventArgs e)
{
e.Cache.DrawString(e.Item.ToString(), e.Appearance.Font, new SolidBrush(Color.White),
e.Bounds, e.Appearance.GetStringFormat());
e.Handled = true;
}
In this case, all items are drawn in Color.White.
Of course, you can test your values via the properties contained in the ListBoxDrawItemEventArgs.
If I click on an item of a list view by mouse, the color becomes that "highlight" color BUT if I do it by code like this:
( MultiSelect should be True and Also I set HideSelection to False)
myListView1.Items[2].Selected = true;
then it will be GRAY...bad! I want it to be the same highlight color when I manually click on them by mouse :(
I also tried adding this code but that didn't work either, Still gray
myListView1.Items[2].BackColor = System.Drawing.Color.Blue;
This is the behaviour of the ListView when it has selected items, but it is not focused.
So, to get the 'blue' colour you are after, just add this;
listView1.Focus();
can you try this please in your listview's SelectedIndexChanged event ?
ListViewItem lv = YourListview.GetItemAt(YourListView.PointToClient(Cursor.Position).X, YourListView.PointToClient(Cursor.Position).Y);
// this kind of Control.GetItemAt() works everywhere you need to find your mouse position ;)
// if you need to find position for screen (i.e. if you want to show a messagebox at the center of screen) you can use PointToScreen instead of PointToClient
if (lv == null)
{
return;
}
else if (yourfirstpossibility == true)
{
lv.Selected = true;
lv.BackColor = Color.FromKnownColor(KnownColor.ButtonHighLight);
// or which color you prefer. FromKnownColor retrieves system colors which you can see in backcolor / forecolor property => "system" named palette
}
a little bit different(more complicated) of this code i use in item_checked event for my listview.. hope it helps you..
In my C# winforms app, I have a datagrid. When the datagrid reloads, I want to set the scrollbar back to where the user had it set. How can I do this?
EDIT: I'm using the old winforms DataGrid control, not the newer DataGridView
You don't actually interact directly with the scrollbar, rather you set the FirstDisplayedScrollingRowIndex. So before it reloads, capture that index, once it's reloaded, reset it to that index.
EDIT: Good point in the comment. If you're using a DataGridView then this will work. If you're using the old DataGrid then the easiest way to do that is to inherit from it. See here: Linkage
The DataGrid has a protected GridVScrolled method that can be used to scroll the grid to a specific row. To use it, derive a new grid from the DataGrid and add a ScrollToRow method.
C# code
public void ScrollToRow(int theRow)
{
//
// Expose the protected GridVScrolled method allowing you
// to programmatically scroll the grid to a particular row.
//
if (DataSource != null)
{
GridVScrolled(this, new ScrollEventArgs(ScrollEventType.LargeIncrement, theRow));
}
}
Yep, definitely FirstDisplayedScrollingRowIndex. You'll need to capture this value after some user interaction, and then after the grid reloads you'll want to set it back to the old value.
For instance, if the reload is triggered by the click of a button, then in the button click handler, you might want to have as your first line a command that places this value into a variable:
// Get current user scroll position
int scrollPosition = myGridView.FirstDisplayedScrollingRowIndex;
// Do some work
...
// Rebind the grid and reset scrolling
myGridView.DataBind;
myGridView.FirstDisplayedScrollingRowIndex = scrollPosition;
Store your vertical and horizontal scroll values into some variable and reset them.
int v= dataGridView1.VerticalScrollingOffset ;
int h= dataGridView1.HorizontalScrollingOffset ;
//...reload
dataGridView1.VerticalScrollingOffset = v;
dataGridView1.HorizontalScrollingOffset =h;
you can save scroll position with next code
int Scroll;
void DataGridView1Scroll(object sender, ScrollEventArgs e)
{
Scroll = dataGridView1.VerticalScrollingOffset;
}
and you can set scroll of dgv to same position after refresing, load dgv... with next code:
PropertyInfo verticalOffset = dataGridView1.GetType().GetProperty("VerticalOffset", BindingFlags.NonPublic |
BindingFlags.Instance);
verticalOffset.SetValue(this.dataGridView1, Scroll, null);
Just posted the answer on the link given by BFree
The DataGrid has a protected GridVScrolled method that can be used to scroll the grid to a specific row. To use it, derive a new grid from the DataGrid and add a ScrollToRow method.
C# code
public void ScrollToRow(int theRow)
{
//
// Expose the protected GridVScrolled method allowing you
// to programmatically scroll the grid to a particular row.
//
if (DataSource != null)
{
GridVScrolled(this, new ScrollEventArgs(ScrollEventType.LargeIncrement, theRow));
}
}
VB.NET code
Public Sub ScrollToRow(ByVal theRow As Integer)
'
' Expose the protected GridVScrolled method allowing you
' to programmatically scroll the grid to a particular row.
'
On Error Resume Next
If Not DataSource Is Nothing Then
GridVScrolled(Me, New ScrollEventArgs(ScrollEventType.LargeIncrement, theRow))
End If
End Sub
I used the answer by #BFree, but also needed to capture the first visible row in the DataGrid:
int indexOfTopMostRow = HitTest(dataGrid.RowHeaderWidth + 10,
dataGrid.PreferredRowHeight + 10).Row;
Even though this is an old question, Many of the solutions above did not work for me. What worked ultimately was:
if(gridEmployees.FirstDisplayedScrollingRowIndex != -1) gridEmployees.FirstDisplayedScrollingRowIndex = 0;