方法: Windows フォーム コントロールに属性を適用する
デザイン環境と正しく対話し、実行時に正常に実行されるコンポーネントとコントロールを開発するには、クラスとメンバーに属性を正しく適用する必要があります。
注意事項
このコンテンツは .NET Framework 用に作成されました。 .NET 6 以降のバージョンを使用している場合は、このコンテンツの使用には注意が必要です。 Windows フォームのデザイナー システムが変更されたため、.NET Framework 以降のデザイナーの変更に関する記事を確認することが重要です。
例
次のコード例は、カスタム コントロールでいくつかの属性を使用する方法を示しています。 このコントロールは、単純なログ記録機能を示します。 コントロールがデータ ソースにバインドされると、データ ソースから送信された値が DataGridView コントロールに表示されます。 値が Threshold
プロパティで指定された値を超えると、ThresholdExceeded
イベントが発生します。
AttributesDemoControl
によって、LogEntry
クラスを持つ値がログされます。 LogEntry
クラスはテンプレート クラスであり、ログに記録される型でパラメーター化されることを意味します。 たとえば、AttributesDemoControl
によって型が float
の値がログに記録されている場合、LogEntry
の各インスタンスは次のように宣言されて使用されます。
// This method handles the timer's Elapsed event. It queries
// the performance counter for the next value, packs the
// value in a LogEntry object, and adds the new LogEntry to
// the list managed by the BindingSource.
private void timer1_Elapsed(
object sender,
System.Timers.ElapsedEventArgs e)
{
// Get the latest value from the performance counter.
float val = this.performanceCounter1.NextValue();
// The performance counter returns values of type float,
// but any type that implements the IComparable interface
// will work.
LogEntry<float> entry = new LogEntry<float>(val, DateTime.Now);
// Add the new LogEntry to the BindingSource list.
this.bindingSource1.Add(entry);
}
' This method handles the timer's Elapsed event. It queries
' the performance counter for the next value, packs the
' value in a LogEntry object, and adds the new LogEntry to
' the list managed by the BindingSource.
Private Sub timer1_Elapsed( _
ByVal sender As Object, _
ByVal e As System.Timers.ElapsedEventArgs) _
Handles timer1.Elapsed
' Get the latest value from the performance counter.
Dim val As Single = Me.performanceCounter1.NextValue()
' The performance counter returns values of type float,
' but any type that implements the IComparable interface
' will work.
Dim entry As LogEntry(Of Single) = _
New LogEntry(Of Single)(val, DateTime.Now)
' Add the new LogEntry to the BindingSource list.
Me.bindingSource1.Add(entry)
End Sub
注意
LogEntry
は任意の型によってパラメーター化されるため、パラメーターの型を操作するにはリフレクションが使用される必要があります。 しきい値機能を機能させるには、パラメーターの型 T
で IComparable インターフェイスが実装される必要があります。
AttributesDemoControl
がホストされるフォームでは、パフォーマンス カウンターを定期的に照会します。 各値は、適切な型の LogEntry
にパッケージ化され、フォームの BindingSource に追加されます。 AttributesDemoControl
では、データ バインディングを通じて値を受け取り、その値を DataGridView コントロールに表示します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Drawing;
using System.Data;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
// This sample demonstrates the use of various attributes for
// authoring a control.
namespace AttributesDemoControlLibrary
{
// This is the event handler delegate for the ThresholdExceeded event.
public delegate void ThresholdExceededEventHandler(ThresholdExceededEventArgs e);
// This control demonstrates a simple logging capability.
[ComplexBindingProperties("DataSource", "DataMember")]
[DefaultBindingProperty("TitleText")]
[DefaultEvent("ThresholdExceeded")]
[DefaultProperty("Threshold")]
[HelpKeywordAttribute(typeof(UserControl))]
[ToolboxItem("System.Windows.Forms.Design.AutoSizeToolboxItem,System.Design")]
public class AttributesDemoControl : UserControl
{
// This backs the Threshold property.
private object thresholdValue;
// The default fore color value for DataGridView cells that
// contain values that exceed the threshold.
private static Color defaultAlertForeColorValue = Color.White;
// The default back color value for DataGridView cells that
// contain values that exceed the threshold.
private static Color defaultAlertBackColorValue = Color.Red;
// The ambient color value.
private static Color ambientColorValue = Color.Empty;
// The fore color value for DataGridView cells that
// contain values that exceed the threshold.
private Color alertForeColorValue = defaultAlertForeColorValue;
// The back color value for DataGridView cells that
// contain values that exceed the threshold.
private Color alertBackColorValue = defaultAlertBackColorValue;
// Child controls that comprise this UserControl.
private TableLayoutPanel tableLayoutPanel1;
private DataGridView dataGridView1;
private Label label1;
// Required for designer support.
private System.ComponentModel.IContainer components = null;
// Default constructor.
public AttributesDemoControl()
{
InitializeComponent();
}
[Category("Appearance")]
[Description("The title of the log data.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Localizable(true)]
[HelpKeywordAttribute("AttributesDemoControlLibrary.AttributesDemoControl.TitleText")]
public string TitleText
{
get
{
return this.label1.Text;
}
set
{
this.label1.Text = value;
}
}
// The inherited Text property is hidden at design time and
// raises an exception at run time. This enforces a requirement
// that client code uses the TitleText property instead.
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
[AmbientValue(typeof(Color), "Empty")]
[Category("Appearance")]
[DefaultValue(typeof(Color), "White")]
[Description("The color used for painting alert text.")]
public Color AlertForeColor
{
get
{
if (this.alertForeColorValue == Color.Empty &&
this.Parent != null)
{
return Parent.ForeColor;
}
return this.alertForeColorValue;
}
set
{
this.alertForeColorValue = value;
}
}
// This method is used by designers to enable resetting the
// property to its default value.
public void ResetAlertForeColor()
{
this.AlertForeColor = AttributesDemoControl.defaultAlertForeColorValue;
}
// This method indicates to designers whether the property
// value is different from the ambient value, in which case
// the designer should persist the value.
private bool ShouldSerializeAlertForeColor()
{
return (this.alertForeColorValue != AttributesDemoControl.ambientColorValue);
}
[AmbientValue(typeof(Color), "Empty")]
[Category("Appearance")]
[DefaultValue(typeof(Color), "Red")]
[Description("The background color for painting alert text.")]
public Color AlertBackColor
{
get
{
if (this.alertBackColorValue == Color.Empty &&
this.Parent != null)
{
return Parent.BackColor;
}
return this.alertBackColorValue;
}
set
{
this.alertBackColorValue = value;
}
}
// This method is used by designers to enable resetting the
// property to its default value.
public void ResetAlertBackColor()
{
this.AlertBackColor = AttributesDemoControl.defaultAlertBackColorValue;
}
// This method indicates to designers whether the property
// value is different from the ambient value, in which case
// the designer should persist the value.
private bool ShouldSerializeAlertBackColor()
{
return (this.alertBackColorValue != AttributesDemoControl.ambientColorValue);
}
[Category("Data")]
[Description("Indicates the source of data for the control.")]
[RefreshProperties(RefreshProperties.Repaint)]
[AttributeProvider(typeof(IListSource))]
public object DataSource
{
get
{
return this.dataGridView1.DataSource;
}
set
{
this.dataGridView1.DataSource = value;
}
}
[Category("Data")]
[Description("Indicates a sub-list of the data source to show in the control.")]
public string DataMember
{
get
{
return this.dataGridView1.DataMember;
}
set
{
this.dataGridView1.DataMember = value;
}
}
// This property would normally have its BrowsableAttribute
// set to false, but this code demonstrates using
// ReadOnlyAttribute, so BrowsableAttribute is true to show
// it in any attached PropertyGrid control.
[Browsable(true)]
[Category("Behavior")]
[Description("The timestamp of the latest entry.")]
[ReadOnly(true)]
public DateTime CurrentLogTime
{
get
{
int lastRowIndex =
this.dataGridView1.Rows.GetLastRow(
DataGridViewElementStates.Visible);
if (lastRowIndex > -1)
{
DataGridViewRow lastRow = this.dataGridView1.Rows[lastRowIndex];
DataGridViewCell lastCell = lastRow.Cells["EntryTime"];
return ((DateTime)lastCell.Value);
}
else
{
return DateTime.MinValue;
}
}
set
{
}
}
[Category("Behavior")]
[Description("The value above which the ThresholdExceeded event will be raised.")]
public object Threshold
{
get
{
return this.thresholdValue;
}
set
{
this.thresholdValue = value;
}
}
// This property exists only to demonstrate the
// PasswordPropertyText attribute. When this control
// is attached to a PropertyGrid control, the returned
// string will be displayed with obscuring characters
// such as asterisks. This property has no other effect.
[Category("Security")]
[Description("Demonstrates PasswordPropertyTextAttribute.")]
[PasswordPropertyText(true)]
public string Password
{
get
{
return "This is a demo password.";
}
}
// This property exists only to demonstrate the
// DisplayName attribute. When this control
// is attached to a PropertyGrid control, the
// property will be appear as "RenamedProperty"
// instead of "MisnamedProperty".
[Description("Demonstrates DisplayNameAttribute.")]
[DisplayName("RenamedProperty")]
public bool MisnamedProperty
{
get
{
return true;
}
}
// This is the declaration for the ThresholdExceeded event.
public event ThresholdExceededEventHandler ThresholdExceeded;
#region Implementation
// This is the event handler for the DataGridView control's
// CellFormatting event. Handling this event allows the
// AttributesDemoControl to examine the incoming log entries
// from the data source as they arrive.
//
// If the cell for which this event is raised holds the
// log entry's timestamp, the cell value is formatted with
// the full date/time pattern.
//
// Otherwise, the cell's value is assumed to hold the log
// entry value. If the value exceeds the threshold value,
// the cell is painted with the colors specified by the
// AlertForeColor and AlertBackColor properties, after which
// the ThresholdExceeded is raised. For this comparison to
// succeed, the log entry's type must implement the IComparable
// interface.
private void dataGridView1_CellFormatting(
object sender,
DataGridViewCellFormattingEventArgs e)
{
try
{
if (e.Value != null)
{
if (e.Value is DateTime)
{
// Display the log entry time with the
// full date/time pattern (long time).
e.CellStyle.Format = "F";
}
else
{
// Scroll to the most recent entry.
DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
DataGridViewCell cell = row.Cells[e.ColumnIndex];
this.dataGridView1.FirstDisplayedCell = cell;
if (this.thresholdValue != null)
{
// Get the type of the log entry.
object val = e.Value;
Type paramType = val.GetType();
// Compare the log entry value to the threshold value.
// Use reflection to call the CompareTo method on the
// template parameter's type.
int compareVal = (int)paramType.InvokeMember(
"CompareTo",
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
e.Value,
new object[] { this.thresholdValue },
System.Globalization.CultureInfo.InvariantCulture);
// If the log entry value exceeds the threshold value,
// set the cell's fore color and back color properties
// and raise the ThresholdExceeded event.
if (compareVal > 0)
{
e.CellStyle.BackColor = this.alertBackColorValue;
e.CellStyle.ForeColor = this.alertForeColorValue;
ThresholdExceededEventArgs teea =
new ThresholdExceededEventArgs(
this.thresholdValue,
e.Value);
this.ThresholdExceeded(teea);
}
}
}
}
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
}
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.label1 = new System.Windows.Forms.Label();
this.tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.AutoSize = true;
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F));
this.tableLayoutPanel1.Controls.Add(this.dataGridView1, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(10, 10);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(10);
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 80F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(425, 424);
this.tableLayoutPanel1.TabIndex = 0;
//
// dataGridView1
//
this.dataGridView1.AllowUserToAddRows = false;
this.dataGridView1.AllowUserToDeleteRows = false;
this.dataGridView1.AllowUserToOrderColumns = true;
this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.dataGridView1.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
this.dataGridView1.ColumnHeadersHeight = 4;
this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGridView1.Location = new System.Drawing.Point(13, 57);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.ReadOnly = true;
this.dataGridView1.RowHeadersVisible = false;
this.dataGridView1.Size = new System.Drawing.Size(399, 354);
this.dataGridView1.TabIndex = 1;
this.dataGridView1.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.dataGridView1_CellFormatting);
//
// label1
//
this.label1.AutoSize = true;
this.label1.BackColor = System.Drawing.SystemColors.Control;
this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
this.label1.Location = new System.Drawing.Point(13, 13);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(399, 38);
this.label1.TabIndex = 2;
this.label1.Text = "label1";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// AttributesDemoControl
//
this.Controls.Add(this.tableLayoutPanel1);
this.Name = "AttributesDemoControl";
this.Padding = new System.Windows.Forms.Padding(10);
this.Size = new System.Drawing.Size(445, 444);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
}
// This is the EventArgs class for the ThresholdExceeded event.
public class ThresholdExceededEventArgs : EventArgs
{
private object thresholdValue = null;
private object exceedingValue = null;
public ThresholdExceededEventArgs(
object thresholdValue,
object exceedingValue)
{
this.thresholdValue = thresholdValue;
this.exceedingValue = exceedingValue;
}
public object ThresholdValue
{
get
{
return this.thresholdValue;
}
}
public object ExceedingValue
{
get
{
return this.exceedingValue;
}
}
}
// This class encapsulates a log entry. It is a parameterized
// type (also known as a template class). The parameter type T
// defines the type of data being logged. For threshold detection
// to work, this type must implement the IComparable interface.
[TypeConverter("LogEntryTypeConverter")]
public class LogEntry<T> where T : IComparable
{
private T entryValue;
private DateTime entryTimeValue;
public LogEntry(
T value,
DateTime time)
{
this.entryValue = value;
this.entryTimeValue = time;
}
public T Entry
{
get
{
return this.entryValue;
}
}
public DateTime EntryTime
{
get
{
return this.entryTimeValue;
}
}
// This is the TypeConverter for the LogEntry class.
public class LogEntryTypeConverter : TypeConverter
{
public override bool CanConvertFrom(
ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(
ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value)
{
if (value is string)
{
string[] v = ((string)value).Split(new char[] { '|' });
Type paramType = typeof(T);
T entryValue = (T)paramType.InvokeMember(
"Parse",
BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod,
null,
null,
new string[] { v[0] },
culture);
return new LogEntry<T>(
entryValue,
DateTime.Parse(v[2]));
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(
ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value,
Type destinationType)
{
if (destinationType == typeof(string))
{
LogEntry<T> le = value as LogEntry<T>;
string stringRepresentation =
String.Format("{0} | {1}",
le.Entry,
le.EntryTime);
return stringRepresentation;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
}
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Diagnostics
Imports System.Drawing
Imports System.Data
Imports System.Reflection
Imports System.Text
Imports System.Windows.Forms
' This sample demonstrates the use of various attributes for
' authoring a control.
Namespace AttributesDemoControlLibrary
' This is the event handler delegate for the ThresholdExceeded event.
Delegate Sub ThresholdExceededEventHandler(ByVal e As ThresholdExceededEventArgs)
' This control demonstrates a simple logging capability.
<ComplexBindingProperties("DataSource", "DataMember"), _
DefaultBindingProperty("TitleText"), _
DefaultEvent("ThresholdExceeded"), _
DefaultProperty("Threshold"), _
HelpKeywordAttribute(GetType(UserControl)), _
ToolboxItem("System.Windows.Forms.Design.AutoSizeToolboxItem,System.Design")> _
Public Class AttributesDemoControl
Inherits UserControl
' This backs the Threshold property.
Private thresholdValue As Object
' The default fore color value for DataGridView cells that
' contain values that exceed the threshold.
Private Shared defaultAlertForeColorValue As Color = Color.White
' The default back color value for DataGridView cells that
' contain values that exceed the threshold.
Private Shared defaultAlertBackColorValue As Color = Color.Red
' The ambient color value.
Private Shared ambientColorValue As Color = Color.Empty
' The fore color value for DataGridView cells that
' contain values that exceed the threshold.
Private alertForeColorValue As Color = defaultAlertForeColorValue
' The back color value for DataGridView cells that
' contain values that exceed the threshold.
Private alertBackColorValue As Color = defaultAlertBackColorValue
' Child controls that comprise this UserControl.
Private tableLayoutPanel1 As TableLayoutPanel
Private WithEvents dataGridView1 As DataGridView
Private label1 As Label
' Required for designer support.
Private components As System.ComponentModel.IContainer = Nothing
' Default constructor.
Public Sub New()
InitializeComponent()
End Sub
<Category("Appearance"), _
Description("The title of the log data."), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), Localizable(True), _
HelpKeywordAttribute("AttributesDemoControlLibrary.AttributesDemoControl.TitleText")> _
Public Property TitleText() As String
Get
Return Me.label1.Text
End Get
Set(ByVal value As String)
Me.label1.Text = value
End Set
End Property
' The inherited Text property is hidden at design time and
' raises an exception at run time. This enforces a requirement
' that client code uses the TitleText property instead.
<Browsable(False), _
EditorBrowsable(EditorBrowsableState.Never), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Overrides Property Text() As String
Get
Throw New NotSupportedException()
End Get
Set(ByVal value As String)
Throw New NotSupportedException()
End Set
End Property
<AmbientValue(GetType(Color), "Empty"), _
Category("Appearance"), _
DefaultValue(GetType(Color), "White"), _
Description("The color used for painting alert text.")> _
Public Property AlertForeColor() As Color
Get
If Me.alertForeColorValue = Color.Empty AndAlso (Me.Parent IsNot Nothing) Then
Return Parent.ForeColor
End If
Return Me.alertForeColorValue
End Get
Set(ByVal value As Color)
Me.alertForeColorValue = value
End Set
End Property
' This method is used by designers to enable resetting the
' property to its default value.
Public Sub ResetAlertForeColor()
Me.AlertForeColor = AttributesDemoControl.defaultAlertForeColorValue
End Sub
' This method indicates to designers whether the property
' value is different from the ambient value, in which case
' the designer should persist the value.
Private Function ShouldSerializeAlertForeColor() As Boolean
Return Me.alertForeColorValue <> AttributesDemoControl.ambientColorValue
End Function
<AmbientValue(GetType(Color), "Empty"), _
Category("Appearance"), _
DefaultValue(GetType(Color), "Red"), _
Description("The background color for painting alert text.")> _
Public Property AlertBackColor() As Color
Get
If Me.alertBackColorValue = Color.Empty AndAlso (Me.Parent IsNot Nothing) Then
Return Parent.BackColor
End If
Return Me.alertBackColorValue
End Get
Set(ByVal value As Color)
Me.alertBackColorValue = value
End Set
End Property
' This method is used by designers to enable resetting the
' property to its default value.
Public Sub ResetAlertBackColor()
Me.AlertBackColor = AttributesDemoControl.defaultAlertBackColorValue
End Sub
' This method indicates to designers whether the property
' value is different from the ambient value, in which case
' the designer should persist the value.
Private Function ShouldSerializeAlertBackColor() As Boolean
Return Me.alertBackColorValue <> AttributesDemoControl.ambientColorValue
End Function 'ShouldSerializeAlertBackColor
<Category("Data"), _
Description("Indicates the source of data for the control."), _
RefreshProperties(RefreshProperties.Repaint), _
AttributeProvider(GetType(IListSource))> _
Public Property DataSource() As Object
Get
Return Me.dataGridView1.DataSource
End Get
Set(ByVal value As Object)
Me.dataGridView1.DataSource = value
End Set
End Property
<Category("Data"), _
Description("Indicates a sub-list of the data source to show in the control.")> _
Public Property DataMember() As String
Get
Return Me.dataGridView1.DataMember
End Get
Set(ByVal value As String)
Me.dataGridView1.DataMember = value
End Set
End Property
' This property would normally have its BrowsableAttribute
' set to false, but this code demonstrates using
' ReadOnlyAttribute, so BrowsableAttribute is true to show
' it in any attached PropertyGrid control.
<Browsable(True), _
Category("Behavior"), _
Description("The timestamp of the latest entry."), _
ReadOnlyAttribute(True)> _
Public Property CurrentLogTime() As DateTime
Get
Dim lastRowIndex As Integer = _
Me.dataGridView1.Rows.GetLastRow(DataGridViewElementStates.Visible)
If lastRowIndex > -1 Then
Dim lastRow As DataGridViewRow = Me.dataGridView1.Rows(lastRowIndex)
Dim lastCell As DataGridViewCell = lastRow.Cells("EntryTime")
Return CType(lastCell.Value, DateTime)
Else
Return DateTime.MinValue
End If
End Get
Set(ByVal value As DateTime)
End Set
End Property
<Category("Behavior"), _
Description("The value above which the ThresholdExceeded event will be raised.")> _
Public Property Threshold() As Object
Get
Return Me.thresholdValue
End Get
Set(ByVal value As Object)
Me.thresholdValue = value
End Set
End Property
' This property exists only to demonstrate the
' PasswordPropertyText attribute. When this control
' is attached to a PropertyGrid control, the returned
' string will be displayed with obscuring characters
' such as asterisks. This property has no other effect.
<Category("Security"), _
Description("Demonstrates PasswordPropertyTextAttribute."), _
PasswordPropertyText(True)> _
Public ReadOnly Property Password() As String
Get
Return "This is a demo password."
End Get
End Property
' This property exists only to demonstrate the
' DisplayName attribute. When this control
' is attached to a PropertyGrid control, the
' property will be appear as "RenamedProperty"
' instead of "MisnamedProperty".
<Description("Demonstrates DisplayNameAttribute."), _
DisplayName("RenamedProperty")> _
Public ReadOnly Property MisnamedProperty() As Boolean
Get
Return True
End Get
End Property
' This is the declaration for the ThresholdExceeded event.
'Public Event ThresholdExceeded As ThresholdExceededEventHandler
Public Event ThresholdExceeded(ByVal e As ThresholdExceededEventArgs)
#Region "Implementation"
' This is the event handler for the DataGridView control's
' CellFormatting event. Handling this event allows the
' AttributesDemoControl to examine the incoming log entries
' from the data source as they arrive.
'
' If the cell for which this event is raised holds the
' log entry's timestamp, the cell value is formatted with
' the full date/time pattern.
'
' Otherwise, the cell's value is assumed to hold the log
' entry value. If the value exceeds the threshold value,
' the cell is painted with the colors specified by the
' AlertForeColor and AlertBackColor properties, after which
' the ThresholdExceeded is raised. For this comparison to
' succeed, the log entry's type must implement the IComparable
' interface.
Private Sub dataGridView1_CellFormatting( _
ByVal sender As Object, _
ByVal e As DataGridViewCellFormattingEventArgs) _
Handles dataGridView1.CellFormatting
Try
If (e.Value IsNot Nothing) Then
If TypeOf e.Value Is DateTime Then
' Display the log entry time with the
' full date/time pattern (long time).
e.CellStyle.Format = "F"
Else
' Scroll to the most recent entry.
Dim row As DataGridViewRow = Me.dataGridView1.Rows(e.RowIndex)
Dim cell As DataGridViewCell = row.Cells(e.ColumnIndex)
Me.dataGridView1.FirstDisplayedCell = cell
If (Me.thresholdValue IsNot Nothing) Then
' Get the type of the log entry.
Dim val As Object = e.Value
Dim paramType As Type = val.GetType()
' Compare the log entry value to the threshold value.
' Use reflection to call the CompareTo method on the
' template parameter's type.
Dim compareVal As Integer = _
Fix(paramType.InvokeMember("CompareTo", _
BindingFlags.Default Or BindingFlags.InvokeMethod, _
Nothing, _
e.Value, _
New Object() {Me.thresholdValue}, _
System.Globalization.CultureInfo.InvariantCulture))
' If the log entry value exceeds the threshold value,
' set the cell's fore color and back color properties
' and raise the ThresholdExceeded event.
If compareVal > 0 Then
e.CellStyle.BackColor = Me.alertBackColorValue
e.CellStyle.ForeColor = Me.alertForeColorValue
Dim teea As New ThresholdExceededEventArgs(Me.thresholdValue, e.Value)
RaiseEvent ThresholdExceeded(teea)
End If
End If
End If
End If
Catch ex As Exception
Trace.WriteLine(ex.Message)
End Try
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso (components IsNot Nothing) Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub
Private Sub InitializeComponent()
Dim DataGridViewCellStyle1 As System.Windows.Forms.DataGridViewCellStyle = New System.Windows.Forms.DataGridViewCellStyle
Me.tableLayoutPanel1 = New System.Windows.Forms.TableLayoutPanel
Me.dataGridView1 = New System.Windows.Forms.DataGridView
Me.label1 = New System.Windows.Forms.Label
Me.tableLayoutPanel1.SuspendLayout()
CType(Me.dataGridView1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'tableLayoutPanel1
'
Me.tableLayoutPanel1.AutoSize = True
Me.tableLayoutPanel1.ColumnCount = 1
Me.tableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100.0!))
Me.tableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100.0!))
Me.tableLayoutPanel1.Controls.Add(Me.dataGridView1, 0, 1)
Me.tableLayoutPanel1.Controls.Add(Me.label1, 0, 0)
Me.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill
Me.tableLayoutPanel1.Location = New System.Drawing.Point(10, 10)
Me.tableLayoutPanel1.Name = "tableLayoutPanel1"
Me.tableLayoutPanel1.Padding = New System.Windows.Forms.Padding(10)
Me.tableLayoutPanel1.RowCount = 2
Me.tableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.0!))
Me.tableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 80.0!))
Me.tableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.0!))
Me.tableLayoutPanel1.Size = New System.Drawing.Size(425, 424)
Me.tableLayoutPanel1.TabIndex = 0
'
'dataGridView1
'
Me.dataGridView1.AllowUserToAddRows = False
Me.dataGridView1.AllowUserToDeleteRows = False
Me.dataGridView1.AllowUserToOrderColumns = True
Me.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dataGridView1.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells
DataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft
DataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control
DataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText
DataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight
DataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText
DataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.[False]
Me.dataGridView1.ColumnHeadersDefaultCellStyle = DataGridViewCellStyle1
Me.dataGridView1.ColumnHeadersHeight = 4
Me.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill
Me.dataGridView1.Location = New System.Drawing.Point(13, 57)
Me.dataGridView1.Name = "dataGridView1"
Me.dataGridView1.ReadOnly = True
Me.dataGridView1.RowHeadersVisible = False
Me.dataGridView1.Size = New System.Drawing.Size(399, 354)
Me.dataGridView1.TabIndex = 1
'
'label1
'
Me.label1.AutoSize = True
Me.label1.BackColor = System.Drawing.SystemColors.Control
Me.label1.Dock = System.Windows.Forms.DockStyle.Fill
Me.label1.Location = New System.Drawing.Point(13, 13)
Me.label1.Name = "label1"
Me.label1.Size = New System.Drawing.Size(399, 38)
Me.label1.TabIndex = 2
Me.label1.Text = "label1"
Me.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'AttributesDemoControl
'
Me.Controls.Add(Me.tableLayoutPanel1)
Me.Name = "AttributesDemoControl"
Me.Padding = New System.Windows.Forms.Padding(10)
Me.Size = New System.Drawing.Size(445, 444)
Me.tableLayoutPanel1.ResumeLayout(False)
Me.tableLayoutPanel1.PerformLayout()
CType(Me.dataGridView1, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
#End Region
End Class
' This is the EventArgs class for the ThresholdExceeded event.
Public Class ThresholdExceededEventArgs
Inherits EventArgs
Private thresholdVal As Object = Nothing
Private exceedingVal As Object = Nothing
Public Sub New(ByVal thresholdValue As Object, ByVal exceedingValue As Object)
Me.thresholdVal = thresholdValue
Me.exceedingVal = exceedingValue
End Sub
Public ReadOnly Property ThresholdValue() As Object
Get
Return Me.thresholdVal
End Get
End Property
Public ReadOnly Property ExceedingValue() As Object
Get
Return Me.exceedingVal
End Get
End Property
End Class
' This class encapsulates a log entry. It is a parameterized
' type (also known as a template class). The parameter type T
' defines the type of data being logged. For threshold detection
' to work, this type must implement the IComparable interface.
<TypeConverter("LogEntryTypeConverter")> _
Public Class LogEntry(Of T As IComparable)
Private entryValue As T
Private entryTimeValue As DateTime
Public Sub New(ByVal value As T, ByVal time As DateTime)
Me.entryValue = value
Me.entryTimeValue = time
End Sub
Public ReadOnly Property Entry() As T
Get
Return Me.entryValue
End Get
End Property
Public ReadOnly Property EntryTime() As DateTime
Get
Return Me.entryTimeValue
End Get
End Property
' This is the TypeConverter for the LogEntry class.
Public Class LogEntryTypeConverter
Inherits TypeConverter
Public Overrides Function CanConvertFrom( _
ByVal context As ITypeDescriptorContext, _
ByVal sourceType As Type) As Boolean
If sourceType Is GetType(String) Then
Return True
End If
Return MyBase.CanConvertFrom(context, sourceType)
End Function
Public Overrides Function ConvertFrom( _
ByVal context As ITypeDescriptorContext, _
ByVal culture As System.Globalization.CultureInfo, _
ByVal value As Object) As Object
If TypeOf value Is String Then
Dim v As String() = CStr(value).Split(New Char() {"|"c})
Dim paramType As Type = GetType(T)
Dim entryValue As T = CType(paramType.InvokeMember("Parse", BindingFlags.Static Or BindingFlags.Public Or BindingFlags.InvokeMethod, Nothing, Nothing, New String() {v(0)}, culture), T)
Return New LogEntry(Of T)(entryValue, DateTime.Parse(v(2))) '
End If
Return MyBase.ConvertFrom(context, culture, value)
End Function
Public Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As Type) As Object
If destinationType Is GetType(String) Then
Dim le As LogEntry(Of T) = CType(value, LogEntry(Of T))
Dim stringRepresentation As String = String.Format("{0} | {1}", le.Entry, le.EntryTime)
Return stringRepresentation
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
End Class
End Namespace
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using AttributesDemoControlLibrary;
// This sample demonstrates using the AttributesDemoControl to log
// data from a data source.
namespace AttributesDemoControlTest
{
public class Form1 : Form
{
private BindingSource bindingSource1;
private System.Diagnostics.PerformanceCounter performanceCounter1;
private Button startButton;
private Button stopButton;
private System.Timers.Timer timer1;
private ToolStripStatusLabel statusStripPanel1;
private NumericUpDown numericUpDown1;
private GroupBox groupBox1;
private GroupBox groupBox2;
private TableLayoutPanel tableLayoutPanel1;
private AttributesDemoControl attributesDemoControl1;
private System.ComponentModel.IContainer components = null;
// This form uses an AttributesDemoControl to display a stream
// of LogEntry objects. The data stream is generated by polling
// a performance counter and communicating the counter values
// to the control with data binding.
public Form1()
{
InitializeComponent();
// Set the initial value of the threshold up/down control
// to the control's threshold value.
this.numericUpDown1.Value =
(decimal)(float)this.attributesDemoControl1.Threshold;
// Assign the performance counter's name to the control's
// title text.
this.attributesDemoControl1.TitleText =
this.performanceCounter1.CounterName;
}
// This method handles the ThresholdExceeded event. It posts
// the value that exceeded the threshold to the status strip.
private void attributesDemoControl1_ThresholdExceeded(
ThresholdExceededEventArgs e)
{
string msg = String.Format(
"{0}: Value {1} exceeded threshold {2}",
this.attributesDemoControl1.CurrentLogTime,
e.ExceedingValue,
e.ThresholdValue);
this.ReportStatus( msg );
}
// This method handles the timer's Elapsed event. It queries
// the performance counter for the next value, packs the
// value in a LogEntry object, and adds the new LogEntry to
// the list managed by the BindingSource.
private void timer1_Elapsed(
object sender,
System.Timers.ElapsedEventArgs e)
{
// Get the latest value from the performance counter.
float val = this.performanceCounter1.NextValue();
// The performance counter returns values of type float,
// but any type that implements the IComparable interface
// will work.
LogEntry<float> entry = new LogEntry<float>(val, DateTime.Now);
// Add the new LogEntry to the BindingSource list.
this.bindingSource1.Add(entry);
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
this.attributesDemoControl1.Threshold =
(float)this.numericUpDown1.Value;
string msg = String.Format(
"Threshold changed to {0}",
this.attributesDemoControl1.Threshold);
this.ReportStatus(msg);
}
private void startButton_Click(object sender, EventArgs e)
{
this.ReportStatus(DateTime.Now + ": Starting");
this.timer1.Start();
}
private void stopButton_Click(object sender, EventArgs e)
{
this.ReportStatus(DateTime.Now + ": Stopping");
this.timer1.Stop();
}
private void ReportStatus(string msg)
{
if (msg != null)
{
this.statusStripPanel1.Text = msg;
}
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.bindingSource1 = new System.Windows.Forms.BindingSource(this.components);
this.performanceCounter1 = new System.Diagnostics.PerformanceCounter();
this.startButton = new System.Windows.Forms.Button();
this.stopButton = new System.Windows.Forms.Button();
this.timer1 = new System.Timers.Timer();
this.statusStripPanel1 = new System.Windows.Forms.ToolStripStatusLabel();
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.attributesDemoControl1 = new AttributesDemoControlLibrary.AttributesDemoControl();
((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.performanceCounter1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// performanceCounter1
//
this.performanceCounter1.CategoryName = ".NET CLR Memory";
this.performanceCounter1.CounterName = "Gen 0 heap size";
this.performanceCounter1.InstanceName = "_Global_";
//
// startButton
//
this.startButton.Location = new System.Drawing.Point(31, 25);
this.startButton.Name = "startButton";
this.startButton.TabIndex = 1;
this.startButton.Text = "Start";
this.startButton.Click += new System.EventHandler(this.startButton_Click);
//
// stopButton
//
this.stopButton.Location = new System.Drawing.Point(112, 25);
this.stopButton.Name = "stopButton";
this.stopButton.TabIndex = 2;
this.stopButton.Text = "Stop";
this.stopButton.Click += new System.EventHandler(this.stopButton_Click);
//
// timer1
//
this.timer1.Interval = 1000;
this.timer1.SynchronizingObject = this;
this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Elapsed);
//
// statusStripPanel1
//
this.statusStripPanel1.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenOuter;
this.statusStripPanel1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.statusStripPanel1.Name = "statusStripPanel1";
this.statusStripPanel1.Text = "Ready";
//
// numericUpDown1
//
this.numericUpDown1.Location = new System.Drawing.Point(37, 29);
this.numericUpDown1.Maximum = new decimal(new int[] {
1410065408,
2,
0,
0});
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.TabIndex = 7;
this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
//
// groupBox1
//
this.groupBox1.Anchor = System.Windows.Forms.AnchorStyles.None;
this.groupBox1.Controls.Add(this.numericUpDown1);
this.groupBox1.Location = new System.Drawing.Point(280, 326);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(200, 70);
this.groupBox1.TabIndex = 13;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Threshold Value";
//
// groupBox2
//
this.groupBox2.Anchor = System.Windows.Forms.AnchorStyles.None;
this.groupBox2.Controls.Add(this.startButton);
this.groupBox2.Controls.Add(this.stopButton);
this.groupBox2.Location = new System.Drawing.Point(26, 327);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(214, 68);
this.groupBox2.TabIndex = 14;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Logging";
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.Controls.Add(this.groupBox2, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.groupBox1, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.attributesDemoControl1, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(10);
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 80F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(514, 411);
this.tableLayoutPanel1.TabIndex = 15;
//
// attributesDemoControl1
//
this.tableLayoutPanel1.SetColumnSpan(this.attributesDemoControl1, 2);
this.attributesDemoControl1.DataMember = "";
this.attributesDemoControl1.DataSource = this.bindingSource1;
this.attributesDemoControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.attributesDemoControl1.Location = new System.Drawing.Point(13, 13);
this.attributesDemoControl1.Name = "attributesDemoControl1";
this.attributesDemoControl1.Padding = new System.Windows.Forms.Padding(10);
this.attributesDemoControl1.Size = new System.Drawing.Size(488, 306);
this.attributesDemoControl1.TabIndex = 0;
this.attributesDemoControl1.Threshold = 200000F;
this.attributesDemoControl1.TitleText = "TITLE";
this.attributesDemoControl1.ThresholdExceeded += new AttributesDemoControlLibrary.ThresholdExceededEventHandler(this.attributesDemoControl1_ThresholdExceeded);
//
// Form1
//
this.BackColor = System.Drawing.SystemColors.Control;
this.ClientSize = new System.Drawing.Size(514, 430);
this.Controls.Add(this.tableLayoutPanel1);
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.performanceCounter1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
this.groupBox1.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
}
}
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Drawing
Imports System.Windows.Forms
Imports AttributesDemoControlLibrary
' This sample demonstrates using the AttributesDemoControl to log
' data from a data source.
Public Class Form1
Inherits Form
Private bindingSource1 As BindingSource
Private performanceCounter1 As System.Diagnostics.PerformanceCounter
Private WithEvents startButton As Button
Private WithEvents stopButton As Button
Private WithEvents timer1 As System.Timers.Timer
Private statusStrip1 As ToolStripStatusLabel
Private statusStripPanel1 As ToolStripStatusLabel
Private WithEvents numericUpDown1 As NumericUpDown
Private groupBox1 As GroupBox
Private groupBox2 As GroupBox
Private tableLayoutPanel1 As TableLayoutPanel
Private WithEvents attributesDemoControl1 As AttributesDemoControl
Private components As System.ComponentModel.IContainer = Nothing
' This form uses an AttributesDemoControl to display a stream
' of LogEntry objects. The data stream is generated by polling
' a performance counter and communicating the counter values
' to the control with data binding.
Public Sub New()
InitializeComponent()
' Set the initial value of the threshold up/down control
' to the control's threshold value.
Me.numericUpDown1.Value = _
System.Convert.ToDecimal( _
System.Convert.ToSingle(Me.attributesDemoControl1.Threshold))
' Assign the performance counter's name to the control's
' title text.
Me.attributesDemoControl1.TitleText = _
Me.performanceCounter1.CounterName
End Sub
' This method handles the ThresholdExceeded event. It posts
' a the value that exceeded the threshold to the status strip.
Private Sub attributesDemoControl1_ThresholdExceeded( _
ByVal e As ThresholdExceededEventArgs) _
Handles attributesDemoControl1.ThresholdExceeded
Dim msg As String = String.Format( _
"{0}: Value {1} exceeded threshold {2}", _
Me.attributesDemoControl1.CurrentLogTime, _
e.ExceedingValue, _
e.ThresholdValue)
Me.ReportStatus(msg)
End Sub
' This method handles the timer's Elapsed event. It queries
' the performance counter for the next value, packs the
' value in a LogEntry object, and adds the new LogEntry to
' the list managed by the BindingSource.
Private Sub timer1_Elapsed( _
ByVal sender As Object, _
ByVal e As System.Timers.ElapsedEventArgs) _
Handles timer1.Elapsed
' Get the latest value from the performance counter.
Dim val As Single = Me.performanceCounter1.NextValue()
' The performance counter returns values of type float,
' but any type that implements the IComparable interface
' will work.
Dim entry As LogEntry(Of Single) = _
New LogEntry(Of Single)(val, DateTime.Now)
' Add the new LogEntry to the BindingSource list.
Me.bindingSource1.Add(entry)
End Sub
Private Sub numericUpDown1_ValueChanged( _
ByVal sender As Object, _
ByVal e As EventArgs) _
Handles numericUpDown1.ValueChanged
Me.attributesDemoControl1.Threshold = _
System.Convert.ToSingle(Me.numericUpDown1.Value)
Dim msg As String = String.Format( _
"Threshold changed to {0}", _
Me.attributesDemoControl1.Threshold)
Me.ReportStatus(msg)
End Sub
Private Sub startButton_Click( _
ByVal sender As Object, _
ByVal e As EventArgs) _
Handles startButton.Click
Me.ReportStatus((DateTime.Now.ToString() + ": Starting"))
Me.timer1.Start()
End Sub
Private Sub stopButton_Click( _
ByVal sender As Object, _
ByVal e As EventArgs) _
Handles stopButton.Click
Me.ReportStatus((DateTime.Now.ToString() + ": Stopping"))
Me.timer1.Stop()
End Sub
Private Sub ReportStatus(msg As String)
If (msg IsNot Nothing) Then
Me.statusStripPanel1.Text = msg
End If
End Sub
<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
If disposing AndAlso (components IsNot Nothing) Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Me.bindingSource1 = New System.Windows.Forms.BindingSource(Me.components)
Me.performanceCounter1 = New System.Diagnostics.PerformanceCounter()
Me.startButton = New System.Windows.Forms.Button()
Me.stopButton = New System.Windows.Forms.Button()
Me.timer1 = New System.Timers.Timer()
Me.statusStripPanel1 = New System.Windows.Forms.ToolStripStatusLabel()
Me.numericUpDown1 = New System.Windows.Forms.NumericUpDown()
Me.groupBox1 = New System.Windows.Forms.GroupBox()
Me.groupBox2 = New System.Windows.Forms.GroupBox()
Me.tableLayoutPanel1 = New System.Windows.Forms.TableLayoutPanel()
Me.attributesDemoControl1 = New AttributesDemoControlLibrary.AttributesDemoControl()
CType(Me.bindingSource1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.performanceCounter1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.timer1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.numericUpDown1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.groupBox1.SuspendLayout()
Me.groupBox2.SuspendLayout()
Me.tableLayoutPanel1.SuspendLayout()
Me.SuspendLayout()
'
' performanceCounter1
'
Me.performanceCounter1.CategoryName = ".NET CLR Memory"
Me.performanceCounter1.CounterName = "Gen 0 heap size"
Me.performanceCounter1.InstanceName = "_Global_"
'
' startButton
'
Me.startButton.Location = New System.Drawing.Point(31, 25)
Me.startButton.Name = "startButton"
Me.startButton.TabIndex = 1
Me.startButton.Text = "Start"
'
' stopButton
'
Me.stopButton.Location = New System.Drawing.Point(112, 25)
Me.stopButton.Name = "stopButton"
Me.stopButton.TabIndex = 2
Me.stopButton.Text = "Stop"
'
' timer1
'
Me.timer1.Interval = 1000
Me.timer1.SynchronizingObject = Me
'
' statusStripPanel1
'
Me.statusStripPanel1.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenOuter
Me.statusStripPanel1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text
Me.statusStripPanel1.Name = "statusStripPanel1"
Me.statusStripPanel1.Text = "Ready"
'
' numericUpDown1
'
Me.numericUpDown1.Location = New System.Drawing.Point(37, 29)
Me.numericUpDown1.Maximum = New Decimal(New Integer() {1410065408, 2, 0, 0})
Me.numericUpDown1.Name = "numericUpDown1"
Me.numericUpDown1.TabIndex = 7
'
' groupBox1
'
Me.groupBox1.Anchor = System.Windows.Forms.AnchorStyles.None
Me.groupBox1.Controls.Add(Me.numericUpDown1)
Me.groupBox1.Location = New System.Drawing.Point(280, 326)
Me.groupBox1.Name = "groupBox1"
Me.groupBox1.Size = New System.Drawing.Size(200, 70)
Me.groupBox1.TabIndex = 13
Me.groupBox1.TabStop = False
Me.groupBox1.Text = "Threshold Value"
'
' groupBox2
'
Me.groupBox2.Anchor = System.Windows.Forms.AnchorStyles.None
Me.groupBox2.Controls.Add(Me.startButton)
Me.groupBox2.Controls.Add(Me.stopButton)
Me.groupBox2.Location = New System.Drawing.Point(26, 327)
Me.groupBox2.Name = "groupBox2"
Me.groupBox2.Size = New System.Drawing.Size(214, 68)
Me.groupBox2.TabIndex = 14
Me.groupBox2.TabStop = False
Me.groupBox2.Text = "Logging"
'
' tableLayoutPanel1
'
Me.tableLayoutPanel1.ColumnCount = 2
Me.tableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F))
Me.tableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F))
Me.tableLayoutPanel1.Controls.Add(Me.groupBox2, 0, 1)
Me.tableLayoutPanel1.Controls.Add(Me.groupBox1, 1, 1)
Me.tableLayoutPanel1.Controls.Add(Me.attributesDemoControl1, 0, 0)
Me.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill
Me.tableLayoutPanel1.Location = New System.Drawing.Point(0, 0)
Me.tableLayoutPanel1.Name = "tableLayoutPanel1"
Me.tableLayoutPanel1.Padding = New System.Windows.Forms.Padding(10)
Me.tableLayoutPanel1.RowCount = 2
Me.tableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 80F))
Me.tableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F))
Me.tableLayoutPanel1.Size = New System.Drawing.Size(514, 411)
Me.tableLayoutPanel1.TabIndex = 15
'
' attributesDemoControl1
'
Me.tableLayoutPanel1.SetColumnSpan(Me.attributesDemoControl1, 2)
Me.attributesDemoControl1.DataMember = ""
Me.attributesDemoControl1.DataSource = Me.bindingSource1
Me.attributesDemoControl1.Dock = System.Windows.Forms.DockStyle.Fill
Me.attributesDemoControl1.Location = New System.Drawing.Point(13, 13)
Me.attributesDemoControl1.Name = "attributesDemoControl1"
Me.attributesDemoControl1.Padding = New System.Windows.Forms.Padding(10)
Me.attributesDemoControl1.Size = New System.Drawing.Size(488, 306)
Me.attributesDemoControl1.TabIndex = 0
Me.attributesDemoControl1.Threshold = 200000F
Me.attributesDemoControl1.TitleText = "TITLE"
'
' Form1
'
Me.BackColor = System.Drawing.SystemColors.Control
Me.ClientSize = New System.Drawing.Size(514, 430)
Me.Controls.Add(tableLayoutPanel1)
Me.Name = "Form1"
Me.Text = "Form1"
CType(Me.bindingSource1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.performanceCounter1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.timer1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.numericUpDown1, System.ComponentModel.ISupportInitialize).EndInit()
Me.groupBox1.ResumeLayout(False)
Me.groupBox2.ResumeLayout(False)
Me.tableLayoutPanel1.ResumeLayout(False)
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
End Class
最初のコード例は、AttributesDemoControl
の実装です。 2 番目のコード例は、AttributesDemoControl
が使用されるフォームを示します。
クラスレベルの属性
一部の属性はクラス レベルで適用されます。 次のコード例は、Windows フォームのコントロールに一般的に適用される属性を示しています。
// This control demonstrates a simple logging capability.
[ComplexBindingProperties("DataSource", "DataMember")]
[DefaultBindingProperty("TitleText")]
[DefaultEvent("ThresholdExceeded")]
[DefaultProperty("Threshold")]
[HelpKeywordAttribute(typeof(UserControl))]
[ToolboxItem("System.Windows.Forms.Design.AutoSizeToolboxItem,System.Design")]
public class AttributesDemoControl : UserControl
{
' This control demonstrates a simple logging capability.
<ComplexBindingProperties("DataSource", "DataMember"), _
DefaultBindingProperty("TitleText"), _
DefaultEvent("ThresholdExceeded"), _
DefaultProperty("Threshold"), _
HelpKeywordAttribute(GetType(UserControl)), _
ToolboxItem("System.Windows.Forms.Design.AutoSizeToolboxItem,System.Design")> _
Public Class AttributesDemoControl
Inherits UserControl
TypeConverter 属性
TypeConverterAttribute は、一般的に使用されるもう 1 つのクラスレベルの属性です。 次のコード例は、LogEntry
クラスに対するその用途を示しています。 また、この例は、LogEntryTypeConverter
と呼ばれる LogEntry
型の TypeConverter の実装も示しています。
// This class encapsulates a log entry. It is a parameterized
// type (also known as a template class). The parameter type T
// defines the type of data being logged. For threshold detection
// to work, this type must implement the IComparable interface.
[TypeConverter("LogEntryTypeConverter")]
public class LogEntry<T> where T : IComparable
{
private T entryValue;
private DateTime entryTimeValue;
public LogEntry(
T value,
DateTime time)
{
this.entryValue = value;
this.entryTimeValue = time;
}
public T Entry
{
get
{
return this.entryValue;
}
}
public DateTime EntryTime
{
get
{
return this.entryTimeValue;
}
}
// This is the TypeConverter for the LogEntry class.
public class LogEntryTypeConverter : TypeConverter
{
public override bool CanConvertFrom(
ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(
ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value)
{
if (value is string)
{
string[] v = ((string)value).Split(new char[] { '|' });
Type paramType = typeof(T);
T entryValue = (T)paramType.InvokeMember(
"Parse",
BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod,
null,
null,
new string[] { v[0] },
culture);
return new LogEntry<T>(
entryValue,
DateTime.Parse(v[2]));
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(
ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value,
Type destinationType)
{
if (destinationType == typeof(string))
{
LogEntry<T> le = value as LogEntry<T>;
string stringRepresentation =
String.Format("{0} | {1}",
le.Entry,
le.EntryTime);
return stringRepresentation;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
' This class encapsulates a log entry. It is a parameterized
' type (also known as a template class). The parameter type T
' defines the type of data being logged. For threshold detection
' to work, this type must implement the IComparable interface.
<TypeConverter("LogEntryTypeConverter")> _
Public Class LogEntry(Of T As IComparable)
Private entryValue As T
Private entryTimeValue As DateTime
Public Sub New(ByVal value As T, ByVal time As DateTime)
Me.entryValue = value
Me.entryTimeValue = time
End Sub
Public ReadOnly Property Entry() As T
Get
Return Me.entryValue
End Get
End Property
Public ReadOnly Property EntryTime() As DateTime
Get
Return Me.entryTimeValue
End Get
End Property
' This is the TypeConverter for the LogEntry class.
Public Class LogEntryTypeConverter
Inherits TypeConverter
Public Overrides Function CanConvertFrom( _
ByVal context As ITypeDescriptorContext, _
ByVal sourceType As Type) As Boolean
If sourceType Is GetType(String) Then
Return True
End If
Return MyBase.CanConvertFrom(context, sourceType)
End Function
Public Overrides Function ConvertFrom( _
ByVal context As ITypeDescriptorContext, _
ByVal culture As System.Globalization.CultureInfo, _
ByVal value As Object) As Object
If TypeOf value Is String Then
Dim v As String() = CStr(value).Split(New Char() {"|"c})
Dim paramType As Type = GetType(T)
Dim entryValue As T = CType(paramType.InvokeMember("Parse", BindingFlags.Static Or BindingFlags.Public Or BindingFlags.InvokeMethod, Nothing, Nothing, New String() {v(0)}, culture), T)
Return New LogEntry(Of T)(entryValue, DateTime.Parse(v(2))) '
End If
Return MyBase.ConvertFrom(context, culture, value)
End Function
Public Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As Type) As Object
If destinationType Is GetType(String) Then
Dim le As LogEntry(Of T) = CType(value, LogEntry(Of T))
Dim stringRepresentation As String = String.Format("{0} | {1}", le.Entry, le.EntryTime)
Return stringRepresentation
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
End Class
メンバーレベルの属性
一部の属性はメンバー レベルで適用されます。 次のコード例は、Windows フォームのコントロールのプロパティに一般的に適用されるいくつかの属性を示します。
[Category("Appearance")]
[Description("The title of the log data.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Localizable(true)]
[HelpKeywordAttribute("AttributesDemoControlLibrary.AttributesDemoControl.TitleText")]
public string TitleText
{
get
{
return this.label1.Text;
}
set
{
this.label1.Text = value;
}
}
<Category("Appearance"), _
Description("The title of the log data."), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), Localizable(True), _
HelpKeywordAttribute("AttributesDemoControlLibrary.AttributesDemoControl.TitleText")> _
Public Property TitleText() As String
Get
Return Me.label1.Text
End Get
Set(ByVal value As String)
Me.label1.Text = value
End Set
End Property
AmbientValue 属性
次の例は AmbientValueAttribute を示し、デザイン環境との相互作用をサポートするコードを示しています。 この相互作用は "アンビエンス" と呼ばれています。
[AmbientValue(typeof(Color), "Empty")]
[Category("Appearance")]
[DefaultValue(typeof(Color), "White")]
[Description("The color used for painting alert text.")]
public Color AlertForeColor
{
get
{
if (this.alertForeColorValue == Color.Empty &&
this.Parent != null)
{
return Parent.ForeColor;
}
return this.alertForeColorValue;
}
set
{
this.alertForeColorValue = value;
}
}
// This method is used by designers to enable resetting the
// property to its default value.
public void ResetAlertForeColor()
{
this.AlertForeColor = AttributesDemoControl.defaultAlertForeColorValue;
}
// This method indicates to designers whether the property
// value is different from the ambient value, in which case
// the designer should persist the value.
private bool ShouldSerializeAlertForeColor()
{
return (this.alertForeColorValue != AttributesDemoControl.ambientColorValue);
}
<AmbientValue(GetType(Color), "Empty"), _
Category("Appearance"), _
DefaultValue(GetType(Color), "White"), _
Description("The color used for painting alert text.")> _
Public Property AlertForeColor() As Color
Get
If Me.alertForeColorValue = Color.Empty AndAlso (Me.Parent IsNot Nothing) Then
Return Parent.ForeColor
End If
Return Me.alertForeColorValue
End Get
Set(ByVal value As Color)
Me.alertForeColorValue = value
End Set
End Property
' This method is used by designers to enable resetting the
' property to its default value.
Public Sub ResetAlertForeColor()
Me.AlertForeColor = AttributesDemoControl.defaultAlertForeColorValue
End Sub
' This method indicates to designers whether the property
' value is different from the ambient value, in which case
' the designer should persist the value.
Private Function ShouldSerializeAlertForeColor() As Boolean
Return Me.alertForeColorValue <> AttributesDemoControl.ambientColorValue
End Function
データバインディングの属性
次の例は、複合データ バインディングの実装を示します。 前に示したクラスレベルの ComplexBindingPropertiesAttribute では、データ バインディングに使用する DataSource
プロパティと DataMember
プロパティを指定します。 AttributeProviderAttribute では、DataSource
プロパティがバインドされる型を指定します。
[Category("Data")]
[Description("Indicates the source of data for the control.")]
[RefreshProperties(RefreshProperties.Repaint)]
[AttributeProvider(typeof(IListSource))]
public object DataSource
{
get
{
return this.dataGridView1.DataSource;
}
set
{
this.dataGridView1.DataSource = value;
}
}
<Category("Data"), _
Description("Indicates the source of data for the control."), _
RefreshProperties(RefreshProperties.Repaint), _
AttributeProvider(GetType(IListSource))> _
Public Property DataSource() As Object
Get
Return Me.dataGridView1.DataSource
End Get
Set(ByVal value As Object)
Me.dataGridView1.DataSource = value
End Set
End Property
[Category("Data")]
[Description("Indicates a sub-list of the data source to show in the control.")]
public string DataMember
{
get
{
return this.dataGridView1.DataMember;
}
set
{
this.dataGridView1.DataMember = value;
}
}
<Category("Data"), _
Description("Indicates a sub-list of the data source to show in the control.")> _
Public Property DataMember() As String
Get
Return Me.dataGridView1.DataMember
End Get
Set(ByVal value As String)
Me.dataGridView1.DataMember = value
End Set
End Property
コードのコンパイル
AttributesDemoControl
がホストされるフォームには、ビルドするためにAttributesDemoControl
アセンブリへの参照が必要です。
関連項目
.NET Desktop feedback