Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Custom UI to Change Line Style in C#

It's easy to change the line style of a plot control using the design time tools in VS.NET. But I would like to present a custom UI to change a selected plot's line style, color, and width. Obviously, width is easy, the color can probably use a ColorDialog, although there may be an easier method, but what about the line style? I would like to offer the user a drop down similar to the one displayed in the "Edit Plots" property browswer (see attached image).

Thanks,
Derek
0 Kudos
Message 1 of 5
(6,927 Views)
You could do this with an owner drawn combo box. The LineStyleComboBox class below is one simple example of how to do this. To use this class, add this code to your project, add an instance of the control to your form, add an event handler for the SelectedIndexChanged event, and then set the LineStyle property when the item changes like this:

void OnSelectedIndexChanged(object sender, EventArgs e)
{
// Assuming a WaveformPlot/ScatterPlot plot member and a LineStyleComboBox
// lineStyles member.
plot.LineStyle = lineStyles.CurrentStyle;
}

The attached screenshot demonstrates what this looks like in an application. Hope this helps.

- Elton

using NationalInstruments;
using NationalInstruments.UI;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace NationalInstruments.DeveloperZone.Demos
{
public class LineStyleComboBox : ComboBox
{
// Define default constants for drawing. Customize these if desired.
private const int ItemPadding = 1;
private static readonly Size DefaultPreviewSize = new Size(32, 24);
private static readonly int DefaultTotalHeight = DefaultPreviewSize.Height + (ItemPadding * 2);

// Define default colors and line width. Could also make these properties for
// additional design-time options.
private static readonly Color PreviewBackgroundColor = Color.Black;
private static readonly Color PreviewForegroundColor = Color.LimeGreen;
private const float PreviewLineWidth = 1.0f;

public LineStyleComboBox()
{
// Specify the combo box will be owner drawn so we can draw the line style.
DrawMode = DrawMode.OwnerDrawFixed;
DropDownStyle = ComboBoxStyle.DropDownList;

// Add all of the line styles to the list.
foreach (LineStyle style in EnumObject.GetValues(typeof(LineStyle)))
Items.Add(style);

// Set the selected item to LineStyle.Solid by default.
SelectedItem = LineStyle.Solid;
}

protected override void OnMeasureItem(MeasureItemEventArgs e)
{
base.OnMeasureItem(e);

// Make the item height the max of the preview height or the label height.
LineStyle currentItem = GetCurrentItemAtIndex(e.Index);
if (currentItem != null)
{
string label = currentItem.ToString();
int labelHeight = (int)(e.Graphics.MeasureString(label, Font).Height);
e.ItemHeight = Math.Max(DefaultTotalHeight, labelHeight);
}
}

protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);

LineStyle currentItem = GetCurrentItemAtIndex(e.Index);
if (currentItem != null)
{
// Draw the background selected if the current item is selected.
if (SelectedItem == currentItem)
e.DrawBackground();

// Calculate the bounds for the line style preview.
Rectangle previewBounds = new Rectangle(
e.Bounds.X + ItemPadding,
e.Bounds.Y + ItemPadding,
DefaultPreviewSize.Width,
e.Bounds.Height - ItemPadding
);

// Fill the background of the line style preview.
using (Brush backgroundBrush = new SolidBrush(PreviewBackgroundColor))
{
e.Graphics.FillRectangle(backgroundBrush, previewBounds);
}

// Draw a preview line for the current line style.
LineStyleDrawArgs styleArgs = new LineStyleDrawArgs(
previewBounds,
PreviewForegroundColor,
PreviewLineWidth
);
using (Pen previewPen = currentItem.CreatePen(this, styleArgs))
{
int yPosition = previewBounds.Y + (previewBounds.Height / 2);
e.Graphics.DrawLine(
previewPen,
new Point(e.Bounds.X, yPosition),
new Point(e.Bounds.X + previewBounds.Width, yPosition)
);
}

// Calculate where to draw the name of the line style.
string label = currentItem.ToString();
SizeF labelSize = e.Graphics.MeasureString(label, e.Font);
float labelX = previewBounds.X + previewBounds.Width + (ItemPadding * 2);
float labelY = e.Bounds.Y + (Math.Abs(e.Bounds.Height - labelSize.Height) / 2);

// Draw the line style label.
using (Brush labelBrush = new SolidBrush(e.ForeColor))
{
e.Graphics.DrawString(label, e.Font, labelBrush, labelX, labelY);
}
}
}

private LineStyle GetCurrentItemAtIndex(int index)
{
LineStyle currentItem = null;
if ((index >= 0) && (index < Items.Count))
currentItem = Items[index] as LineStyle;

return currentItem;
}

// Provide convenience property to get the selected style.
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public LineStyle CurrentStyle
{
get
{
return SelectedItem as LineStyle;
}
}

// Shadow the Items property to hide it from the Windows Forms designer.
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public new ComboBox.ObjectCollection Items
{
get
{
return base.Items;
}
}
}
}
Message 2 of 5
(6,927 Views)
Elton,

You da man! This is exactly what I was looking for. Just a question on the LineStyleComboBox, though. I see you've added designer attributes. Did you compile it into it's own dll and then add it to the toolbox or are you just creating it "by hand" in the form?

Thanks again,
Derek
0 Kudos
Message 3 of 5
(6,927 Views)
You could do that. Another thing you could do is add the class to your project, compile once, drop a regular ComboBox on your Form, go to the code view, change the ComboBox declaration and instantation to LineStyleComboBox, go back to the designer, and then you will then see the LineStyleComboBox in the Windows Forms designer. This is what I did when I wrote the example.

- Elton
0 Kudos
Message 4 of 5
(6,927 Views)
That's a neat trick! Here's a link to a custom Color ComboBox if you're interested:

http://www.syncfusion.com/FAQ/WinForms/FAQ_c88c.asp#q547q

Thanks again,
Derek
0 Kudos
Message 5 of 5
(6,927 Views)