Currency symbol Align left and values align right in GridView - c#

Is it possible to align currency symbol to the left and the value to the right in DevExpress GridView?

This task is beyond the regular text formatting. To accomplish it, you need to manually draw the cell content.
XtraGrid provides the event for this purpose: CustomDrawCell. The event argument object provides a reference to graphics objects, cell boundaries, and other information necessary to draw the cell text manually.
private void OnGridViewCustomDrawCell(object sender, RowCellCustomDrawEventArgs e) {
switch (e.Column.FieldName) {
case "Debit":
DrawDebitCell(e);
break;
}
}
private void DrawDebitCell(RowCellCustomDrawEventArgs e) {
e.Handled = true;
string text = string.Format(CultureInfo.CurrentCulture, "{0} {1:n2}", CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol, e.CellValue);
Size textSize = e.Appearance.CalcTextSizeInt(e.Cache, text, int.MaxValue);
e.Appearance.DrawBackground(e.Cache, e.Bounds);
if (Convert.ToInt32(textSize.Width) > e.Bounds.Width)
e.Appearance.DrawString(e.Cache, text, e.Bounds);
else {
StringFormat stringFormat = e.Appearance.GetStringFormat();
string valueText = string.Format(CultureInfo.CurrentCulture, "{0:n2}", e.CellValue);
stringFormat.Alignment = StringAlignment.Near;
e.Appearance.DrawString(e.Cache, CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol, e.Bounds, e.Appearance.Font, stringFormat);
stringFormat.Alignment = StringAlignment.Far;
e.Appearance.DrawString(e.Cache, valueText, e.Bounds, e.Appearance.Font, stringFormat);
}
}
This approach has a few disadvantages:
The manually drawn cell content is not used by built in Export and Printing system
It is necessary to calculate the text width to make sure that the value and the currency symbol will not overlap each other. For this purpose, you can use the CalcTextSizeInt method of the AppearanceObject object available via event arguments. DevExpress uses its own text rendering engine, so the standard Graphics.MeasureString method is not useful in this case

Related

WinForms: Changing ForeColor of Selected item in ListView

I am setting the ForeColor of all items in my ListView to a different color, but this get's overrided when the item is selected (changes to Black again; changes back to custom color on deselection).
I want my items to retain my custom color, even in selection.
I'm basically asking the same question that was asked here 7 years ago, and doesn't seem to have any satisfactory answer.
I tried searching in SO and elsewhere, and no luck. The only solution provided so far is to draw the whole thing (the DrawItem method), which I gave a try but is ridiculously complicated for such a petty requirement...
Is this the only way? Say it ain't so.
Enable your ListView OwnerDraw mode, then subscribe its DrawItem and DrawColumnHeader events.
If your design requires it, also subcribe the DrawSubitem event.
At this point, you can draw anything in the related areas of your ListView.
In the example, I've painted a little symbol in the Header area.
The Header text needs to be painted too.
If the Background color doesn't change (same as in design mode), you just need to use the DrawListViewItemEventArgs e parameter function e.DrawBackground();
If not, use e.Graphics.FillRectangle() to color the Item area, defined by e.Bounds.
The Item Text is drawn using e.Graphics.DrawString().
The item Text is e.Item.Text, the text area is defined by e.Bounds again.
If you don't need any specific details/settings for the item's text, you can simply use e.DrawText();, which uses the default properties (defined at design-time).
Here, the item color complex logic is that the color is specified inside the item text. Could be anything else. The item tag, its Index position, a List<Parameters>, you name it.
This is how it might look like:
(I added e.Graphics.TextRenderingHint = [] to show how you can control the quality of the rendered text. e.Graphics.TextContrast can be also used to enhance the contrast).
Note: this code sample only draws a generic image, if the ListView has an ImageList. You should also verify whether the SmallIcon/LargeIcon ImageLists are defined and draw the related Image in the specified size. It's the same procedure, though.
protected void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
e.Item.UseItemStyleForSubItems = true;
int imageOffset = 0;
Rectangle rect = e.Item.Bounds;
bool drawImage = !(e.Item.ImageList is null);
Color itemColor = Color.FromName(e.Item.Text.Substring(e.Item.Text.LastIndexOf(" ") + 1));
using (var format = new StringFormat(StringFormatFlags.FitBlackBox)) {
format.LineAlignment = StringAlignment.Center;
if (drawImage) {
imageOffset = e.Item.ImageList.ImageSize.Width + 1;
rect.Location = new Point(e.Bounds.X + imageOffset, e.Item.Bounds.Y);
rect.Size = new Size(e.Bounds.Width - imageOffset, e.Item.Bounds.Height);
e.Graphics.DrawImage(e.Item.ImageList.Images[e.Item.ImageIndex], e.Bounds.Location);
}
if (e.Item.Selected) {
using (var bkgrBrush = new SolidBrush(itemColor))
using (var foreBrush = new SolidBrush(e.Item.BackColor)) {
e.Graphics.FillRectangle(bkgrBrush, rect);
e.Graphics.DrawString(e.Item.Text, e.Item.Font, foreBrush, rect, format);
}
e.DrawFocusRectangle();
}
else {
//e.DrawDefault = true;
using (var foreBrush = new SolidBrush(itemColor)) {
e.Graphics.DrawString(e.Item.Text, e.Item.Font, foreBrush, rect, format);
}
}
}
}
// Draws small symbol in the Header beside the normal Text
protected void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.DrawBackground();
string extra = (e.ColumnIndex == 1) ? (char)32 + "\u2660" + (char)32 : (char)32 + "\u2663" + (char)32;
using (var brush = new SolidBrush(e.ForeColor)) {
e.Graphics.DrawString(extra + e.Header.Text, e.Font, brush, e.Bounds, StringFormat.GenericTypographic);
}
}

How to disable a textbox without fading text?

Is there anyway of getting all of the properties of a !enabled textbox except the faded text?
I cannot use a Label because I want the textbox to be enabled eventually. I cannot use readonly because I do not want the user's cursor to appear within.
It would be best to have both a Label and a TextBox in the same location.
Hide the TextBox and display the content in a Label until you are ready to edit it.
At that point, hide the Label and show the TextBox.
Otherwise you'll have to subclass the TextBox, and override the OnPaint method, somewhat like the following:
protected override void OnPaint(PaintEventArgs e)
{
SolidBrush drawBrush = new SolidBrush(ForeColor); //Use the ForeColor property
// Draw string to screen.
e.Graphics.DrawString(Text, Font, drawBrush, 0f,0f); //Use the Font property
}
Take a look at this answer and this link.
Use a SystemColor instead of KnownColor:
Color color = textbox1.BackColor ;
textbox1.BackColor = System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B);
color = textbox1.ForeColor ;
textbox1.ForeColor = System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B);

Adding multiple external fonts to my winform application

I would like to add or deploy the app with more than 10 external fonts from my resource folder. I have gone through various SO questions but none of them suits my requirement except this SO answer.
Now I have implemeted the same thing in my winform app and I would like to add these fonts to combo box with their styles such as shown below.
Any suggestions are most welcome.
You have to draw the items in the ComboBox yourself if you want to show them in the drop down in their appropriate font. This isn't hard, the following code does the bare minimum:
var comboBox = new ComboBox();
comboBox.DisplayMember = "Name";
comboBox.Items.AddRange(FontFamily.Families);
comboBox.DrawMode = DrawMode.OwnerDrawFixed;
comboBox.DrawItem += (s, e) => {
var fontFamily = (FontFamily) comboBox.Items[e.Index];
var itemText = comboBox.GetItemText(fontFamily);
// Some fonts don't work with a regular style, if they don't have a
// regular style, we'll default to the provided font.
if (!fontFamily.IsStyleAvailable(FontStyle.Regular))
{
TextRenderer.DrawText(
e.Graphics, itemText, e.Font, e.Bounds, e.ForeColor, e.BackColor
TextFormatFlags.VerticalCenter | TextFormatFlags.Left);
}
else
{
using (var font = new Font(fontFamily, comboBox.Font.Size, FontStyle.Regular))
{
TextRenderer.DrawText(
e.Graphics, itemText, font, e.Bounds, e.ForeColor, e.BackColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left);
}
}
};
This implementation handles a FontFamily not having a regular font style by falling back to the ComboBox's default font. You can handle this more gracefully by attempting to find a valid style for the FontFamily before creating the font.

Set Text to the lowest right edge of a label?

Easy example, lets say I'm creating a Label like that:
Label label = new Label();
label.Text = "Hello" + "20.50";
label.Width = 250;
label.Height = 100;
panel1.Controls.Add(label);
How could I say that the "20.50" should appear in the lowest right edge of the label?
For clarity I made a little example in word:
How could I achieve this? Any help appreciated!
There's no built-in support for this with a Label control. You'll need to inherit from Label to create a custom control, and then write the painting code yourself.
Of course, you'll also need some way to differentiate between the two strings. The + sign, when applied to two strings, is concatenation. The two strings are joined together by the compiler, so all you get is this: Hello20.50. You will either need to use two separate properties, each with their own strings, or insert some sort of delimiter in between the two strings that you can use to split them apart later. Since you're already creating a custom control class, I'd go with the separate properties—much cleaner code, and harder to get wrong.
public class CornerLabel : Label
{
public string Text2 { get; set; }
public CornerLabel()
{
// This label doesn't support autosizing because the default autosize logic
// only knows about the primary caption, not the secondary one.
//
// You will either have to set its size manually, or override the
// GetPreferredSize function and write your own logic. That would not be
// hard to do: use TextRenderer.MeasureText to determine the space
// required for both of your strings.
this.AutoSize = false;
}
protected override void OnPaint(PaintEventArgs e)
{
// Call the base class to paint the regular caption in the top-left.
base.OnPaint(e);
// Paint the secondary caption in the bottom-right.
TextRenderer.DrawText(e.Graphics,
this.Text2,
this.Font,
this.ClientRectangle,
this.ForeColor,
TextFormatFlags.Bottom | TextFormatFlags.Right);
}
}
Add this class to a new file, build your project, and then drop this control onto your form. Make sure to set both the Text and Text2 properties, and then resize the control in the designer and watch what happens!
Here is what you need, a custom label:
public class CustomLabel : Label
{
public CustomLabel()
{
TopLeftText = BottomRightText = "";
AutoSize = false;
}
public string TopLeftText {get;set;}
public string BottomRightText {get;set;}
protected override void OnPaint(PaintEventArgs e)
{
using (StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Near})
{
using(SolidBrush brush = new SolidBrush(ForeColor)){
e.Graphics.DrawString(TopLeftText, Font, brush, ClientRectangle, sf);
sf.LineAlignment = StringAlignment.Far;
sf.Alignment = StringAlignment.Far;
e.Graphics.DrawString(BottomRightText, Font, brush, ClientRectangle, sf);
}
}
}
}
//use it:
//first, set its size to what you want.
customLabel1.TopLeftText = house.Name;
customLabel2.BottomRightText = house.Number;

Draw and Clear String over a Control C#

After some search at Google I had some examples but none of them gave me what I need.
I need to write a String (WriteString()) into a Control in WinForm on a ButtonClick and I need to update that Draw, because i'm trying to write the Date into the Control, the System Date.
So each time the user clicks on that Button the DateTime.Now.ToString(); should be drawn into the Control.
Bests
draw a string on label
this url will surely help you
the code written there is
void Label_OnPaint(object sender, PaintEventArgs e) {
base.OnPaint(e);
Label lbl = sender as Label;
if (lbl != null) {
string Text = lbl.Text;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
if (myShowShadow) { // draw the shadow first!
e.Graphics.DrawString(Text, lbl.Font, new SolidBrush(myShadowColor), myShadowOffset, StringFormat.GenericDefault);
}
e.Graphics.DrawString(Text, lbl.Font, new SolidBrush(lbl.ForeColor), 0, 0, StringFormat.GenericDefault);
}
}
You should consider using a winforms Label and a Timer for that.
Or you could modify the OnPaint method of the control to override how the control is painted. There is a method in the Graphics object that lets you write a string g.DrawString

Categories