Ice*_*ind 2 c# datagridview custom-controls winforms
我用谷歌搜索了这个问题的答案,但我似乎无法找到任何好的实例.我创建了一个名为StarControl的自定义星级用户控件.控件基本上是五个相互水平相邻的图片框,我有以下代码:
public partial class StarControl : UserControl
{
private enum StarTypes
{
Hollow,
Filled
}
private readonly StarTypes[] _stars;
private int _rating;
public StarControl()
{
InitializeComponent();
Locked = false;
_stars = new StarTypes[5];
_stars[0] = StarTypes.Hollow;
_stars[1] = StarTypes.Hollow;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
Rating = 0;
SetStars();
}
public bool Locked
{
get;
set;
}
public int Rating
{
get { return _rating; }
set { _rating = value; SetRating(); }
}
private void SetRating()
{
if (_rating == 0)
{
_stars[0] = StarTypes.Hollow;
_stars[1] = StarTypes.Hollow;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
}
if (_rating == 1)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Hollow;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
}
if (_rating == 2)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Filled;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
}
if (_rating == 3)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Filled;
_stars[2] = StarTypes.Filled;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
}
if (_rating == 4)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Filled;
_stars[2] = StarTypes.Filled;
_stars[3] = StarTypes.Filled;
_stars[4] = StarTypes.Hollow;
}
if (_rating == 5)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Filled;
_stars[2] = StarTypes.Filled;
_stars[3] = StarTypes.Filled;
_stars[4] = StarTypes.Filled;
}
SetStars();
}
private void SetStars()
{
pbStar1.Image = _stars[0] == StarTypes.Hollow
? Properties.Resources.star_hollow
: Properties.Resources.star_filled;
pbStar2.Image = _stars[1] == StarTypes.Hollow
? Properties.Resources.star_hollow
: Properties.Resources.star_filled;
pbStar3.Image = _stars[2] == StarTypes.Hollow
? Properties.Resources.star_hollow
: Properties.Resources.star_filled;
pbStar4.Image = _stars[3] == StarTypes.Hollow
? Properties.Resources.star_hollow
: Properties.Resources.star_filled;
pbStar5.Image = _stars[4] == StarTypes.Hollow
? Properties.Resources.star_hollow
: Properties.Resources.star_filled;
}
private void PbStar1MouseEnter(object sender, EventArgs e)
{
if (!Locked)
{
pbStar1.Image = Properties.Resources.star_filled;
pbStar2.Image = Properties.Resources.star_hollow;
pbStar3.Image = Properties.Resources.star_hollow;
pbStar4.Image = Properties.Resources.star_hollow;
pbStar5.Image = Properties.Resources.star_hollow;
}
}
private void PbStar1MouseLeave(object sender, EventArgs e)
{
if (!Locked)
{
SetStars();
}
}
private void PbStar2MouseEnter(object sender, EventArgs e)
{
if (!Locked)
{
pbStar1.Image = Properties.Resources.star_filled;
pbStar2.Image = Properties.Resources.star_filled;
pbStar3.Image = Properties.Resources.star_hollow;
pbStar4.Image = Properties.Resources.star_hollow;
pbStar5.Image = Properties.Resources.star_hollow;
}
}
private void PbStar2MouseLeave(object sender, EventArgs e)
{
if (!Locked)
{
SetStars();
}
}
private void PbStar3MouseEnter(object sender, EventArgs e)
{
if (!Locked)
{
pbStar1.Image = Properties.Resources.star_filled;
pbStar2.Image = Properties.Resources.star_filled;
pbStar3.Image = Properties.Resources.star_filled;
pbStar4.Image = Properties.Resources.star_hollow;
pbStar5.Image = Properties.Resources.star_hollow;
}
}
private void PbStar3MouseLeave(object sender, EventArgs e)
{
if (!Locked)
{
SetStars();
}
}
private void PbStar4MouseEnter(object sender, EventArgs e)
{
if (!Locked)
{
pbStar1.Image = Properties.Resources.star_filled;
pbStar2.Image = Properties.Resources.star_filled;
pbStar3.Image = Properties.Resources.star_filled;
pbStar4.Image = Properties.Resources.star_filled;
pbStar5.Image = Properties.Resources.star_hollow;
}
}
private void PbStar4MouseLeave(object sender, EventArgs e)
{
if (!Locked)
{
SetStars();
}
}
private void PbStar5MouseEnter(object sender, EventArgs e)
{
if (!Locked)
{
pbStar1.Image = Properties.Resources.star_filled;
pbStar2.Image = Properties.Resources.star_filled;
pbStar3.Image = Properties.Resources.star_filled;
pbStar4.Image = Properties.Resources.star_filled;
pbStar5.Image = Properties.Resources.star_filled;
}
}
private void PbStar5MouseLeave(object sender, EventArgs e)
{
if (!Locked)
{
SetStars();
}
}
private void PbStar1MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && !Locked)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Hollow;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
Rating = 1;
}
if (e.Button == MouseButtons.Right && !Locked)
{
_stars[0] = StarTypes.Hollow;
_stars[1] = StarTypes.Hollow;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
Rating = 0;
}
SetStars();
}
private void PbStar2MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && !Locked)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Filled;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
Rating = 2;
}
if (e.Button == MouseButtons.Right && !Locked)
{
_stars[0] = StarTypes.Hollow;
_stars[1] = StarTypes.Hollow;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
Rating = 0;
}
SetStars();
}
private void PbStar3MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && !Locked)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Filled;
_stars[2] = StarTypes.Filled;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
Rating = 3;
}
if (e.Button == MouseButtons.Right && !Locked)
{
_stars[0] = StarTypes.Hollow;
_stars[1] = StarTypes.Hollow;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
Rating = 0;
}
SetStars();
}
private void PbStar4MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && !Locked)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Filled;
_stars[2] = StarTypes.Filled;
_stars[3] = StarTypes.Filled;
_stars[4] = StarTypes.Hollow;
Rating = 4;
}
if (e.Button == MouseButtons.Right && !Locked)
{
_stars[0] = StarTypes.Hollow;
_stars[1] = StarTypes.Hollow;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
Rating = 0;
}
SetStars();
}
private void PbStar5MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && !Locked)
{
_stars[0] = StarTypes.Filled;
_stars[1] = StarTypes.Filled;
_stars[2] = StarTypes.Filled;
_stars[3] = StarTypes.Filled;
_stars[4] = StarTypes.Filled;
Rating = 5;
}
if (e.Button == MouseButtons.Right && !Locked)
{
_stars[0] = StarTypes.Hollow;
_stars[1] = StarTypes.Hollow;
_stars[2] = StarTypes.Hollow;
_stars[3] = StarTypes.Hollow;
_stars[4] = StarTypes.Hollow;
Rating = 0;
}
SetStars();
}
}
Run Code Online (Sandbox Code Playgroud)
控件工作得很好.在我的表单上,我有一个DataGridView控件,我正在尝试使用集合中的行动态填充DataGridView.该集合只是这个类的集合:
[Serializable]
public class Rating
{
public string VendorName { get; set; }
public int VendorRating { get; set; }
}
public List<Rating> _myRatings;
Run Code Online (Sandbox Code Playgroud)
VendorName只是一个字符串,VendorRating是一个int,表示0-5之间的数字.通过设置我的Rating属性StarControl,它将显示该数量的星星.我正在尝试做的是弄清楚如何让我的StarControl用户控件显示在DataGridView.有人可以请我提供一个如何做到这一点的例子吗?
我已经看过这篇关于这个主题的MSDN文章,但我不认为这适用于我,因为它们只是继承自己DataGridViewTextBoxCell,我的控件比日期/时间文本框更复杂.
出于这样的目的,您根本不需要这样的控制.附件与DataGridView有点棘手.我不想在这种方法后给你一个解决方案,但我只想分享一些关于如何实现它的信息.首先,您必须计算显示的总单元格数,您需要List<YourControl>存储所有需要的控件.这些控制必须将你的DataGridView作为他们的Parent.这些控件的数量必须等于显示的单元格数.然后在CellPainting事件处理程序中,您必须更新列表中所有控件的位置.我们在CellPainting事件处理程序中添加位置更新代码,因为无论何时更新单元格值和边界,都会触发CellPainting并相应地更新控件Location.这有点棘手,但确实有效.您可以通过某些引用属性(例如Tag属性)将每个控件与每个单元关联.
现在,我想与您分享这种更好的方法.你只需创建一个自定义DataGridViewCell使用CellTemplate自定义DataGridViewColumn.我们必须做一些绘画GDI+并编写相当多的代码.请注意,我为自己编写了这个演示,但是在阅读完问题之后就开始了.用这样一个完整的代码回答问题并不是很有趣,它耗费了很多时间,但正如我所说,我打算自己使用这个演示,现在我只想和你分享.实际上为了给你一些想法,代码可以简化得更多:
public class DataGridViewRatingColumn : DataGridViewColumn {
public DataGridViewRatingColumn() : base(new DataGridViewRatingCell()) {
base.ReadOnly = true;
RatedStarColor = Color.Green;
GrayStarColor = Color.LightGray;
StarScale = 1;
}
bool readOnly;
public new bool ReadOnly
{
get {
return readOnly;
}
set {
readOnly = value;
}
}
Color ratedStarColor;
Color grayStarColor;
float starScale;
public Color RatedStarColor {
get { return ratedStarColor; }
set {
if (ratedStarColor != value) {
ratedStarColor = value;
if (DataGridView != null) DataGridView.InvalidateColumn(Index);
}
}
}
public Color GrayStarColor
{
get { return grayStarColor; }
set {
if (grayStarColor != value){
grayStarColor = value;
if(DataGridView != null) DataGridView.InvalidateColumn(Index);
}
}
}
public float StarScale {
get { return starScale; }
set {
if (starScale != value) {
starScale = value;
DataGridViewRatingCell.UpdateBrushes(value);
if (DataGridView != null) DataGridView.InvalidateColumn(Index);
}
}
}
}
public class DataGridViewRatingCell : DataGridViewTextBoxCell {
static DataGridViewRatingCell() {
//Init star
List<PointF> points = new List<PointF>();
bool largeArc = true;
R = 10;
r = 4;
center = new Point(R, R);
for (float alpha = 90; alpha <= 414; alpha += 36)
{
int d = largeArc ? R : r;
double radAlpha = alpha * Math.PI / 180;
float x = (float)(d * Math.Cos(radAlpha));
float y = (float)(d * Math.Sin(radAlpha));
points.Add(new PointF(center.X + x, center.Y + y));
largeArc = !largeArc;
}
star.AddPolygon(points.ToArray());
star.Transform(new Matrix(1, 0, 0, -1, 0, center.Y * 2));
//Init stars
UpdateBrushes(1);
}
public DataGridViewRatingCell() {
ValueType = typeof(int);
ratedStarColor = Color.Green;
grayStarColor = Color.LightGray;
starScale = 1;
UseColumnStarColor = true;
UseColumnStarScale = true;
}
public override object DefaultNewRowValue {
get {
return 0;
}
}
internal static void UpdateBrushes(float scale) {
int space = 2*R;
for (int i = 0; i < 5; i++) {
if (stars[i] != null) stars[i].Dispose();
stars[i] = (GraphicsPath)star.Clone();
stars[i].Transform(new Matrix(scale, 0, 0, scale, space * i * scale, 0));
brushes[i] = CreateBrush(new RectangleF(center.X - R + space * i * scale, center.Y - R, R * 2 * scale, R * 2 * scale));
}
}
private static LinearGradientBrush CreateBrush(RectangleF bounds)
{
var brush = new LinearGradientBrush(bounds,Color.White, Color.Yellow, LinearGradientMode.ForwardDiagonal);
ColorBlend cb = new ColorBlend();
Color c = Color.Green;
Color lightColor = Color.White;
cb.Colors = new Color[] { c, c, lightColor, c, c };
cb.Positions = new float[] { 0, 0.4f, 0.5f, 0.6f, 1 };
brush.InterpolationColors = cb;
return brush;
}
private void AdjustBrushColors(LinearGradientBrush brush, Color baseColor, Color lightColor)
{
//Note how we adjust the colors, using brush.InterpolationColors directly won't work.
ColorBlend cb = brush.InterpolationColors;
cb.Colors = new Color[] { baseColor, baseColor, lightColor, baseColor, baseColor };
brush.InterpolationColors = cb;
}
static GraphicsPath star = new GraphicsPath();
static GraphicsPath[] stars = new GraphicsPath[5];
static LinearGradientBrush[] brushes = new LinearGradientBrush[5];
static Point center;
static int R, r;
int currentValue = -1;
bool mouseOver;
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds,
int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue,
string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue,
errorText, cellStyle, advancedBorderStyle, paintParts & ~DataGridViewPaintParts.SelectionBackground & ~DataGridViewPaintParts.ContentForeground);
if (rowIndex == RowIndex && (paintParts & DataGridViewPaintParts.ContentForeground) != 0) {
graphics.SmoothingMode = SmoothingMode.AntiAlias;
if(Value != null) Value = Math.Min(Math.Max(0, (int)Value), 5);
if (!mouseOver) currentValue = (int)(Value ?? 0);
PaintStars(graphics, cellBounds, 0, currentValue, true);
PaintStars(graphics, cellBounds, currentValue, 5 - currentValue, false);
graphics.SmoothingMode = SmoothingMode.Default;
}
}
protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) {
base.OnMouseMove(e);
if (!mouseOver) mouseOver = true;
if (IsReadOnly()) return;
var lastStar = stars.Select((x, i) => new { x, i })
.LastOrDefault(x => x.x.IsVisible(e.Location));
if (lastStar != null) {
currentValue = lastStar.i + 1;
DataGridView.Cursor = Cursors.Hand;
}
else if(RowIndex > -1) {
currentValue = (int)(Value ?? 0);
DataGridView.Cursor = Cursors.Default;
}
DataGridView.InvalidateCell(this);
}
protected override void OnClick(DataGridViewCellEventArgs e) {
base.OnClick(e);
if (IsReadOnly()) return;
Value = currentValue == 1 && (int?) Value == 1 ? 0 : currentValue;
}
protected override void OnMouseLeave(int rowIndex) {
base.OnMouseLeave(rowIndex);
mouseOver = false;
if (IsReadOnly()) return;
if (rowIndex == RowIndex) {
currentValue = (int)(Value ?? 0);
DataGridView.InvalidateCell(this);
}
}
private bool IsReadOnly() {
var col = OwningColumn as DataGridViewRatingColumn;
return col != null ? col.ReadOnly : false;
}
private void PaintStars(Graphics g, Rectangle bounds, int startIndex, int count, bool rated) {
GraphicsState gs = g.Save();
g.TranslateTransform(bounds.Left, bounds.Top);
var col = OwningColumn as DataGridViewRatingColumn;
Color ratedColor = col == null ? Color.Yellow :
UseColumnStarColor ? col.RatedStarColor : RatedStarColor;
Color grayColor = col == null ? Color.LightGray :
UseColumnStarColor ? col.GrayStarColor : GrayStarColor;
float starScale = col == null ? 1 :
UseColumnStarScale ? col.StarScale : StarScale;
UpdateBrushes(starScale);
for(int i = startIndex; i < startIndex + count; i++) {
AdjustBrushColors(brushes[i], rated ? ratedColor : grayColor, rated ? Color.White : grayColor);
g.FillPath(brushes[i], stars[i]);
//g.DrawPath(Pens.Green, stars[i]);
}
g.Restore(gs);
}
Color ratedStarColor;
Color grayStarColor;
float starScale;
public Color RatedStarColor {
get { return ratedStarColor; }
set {
if (ratedStarColor != value) {
ratedStarColor = value;
var col = OwningColumn as DataGridViewRatingColumn;
if (col != null && col.RatedStarColor != value) {
UseColumnStarColor = false;
DataGridView.InvalidateCell(this);
}
}
}
}
public Color GrayStarColor {
get { return grayStarColor; }
set {
if (grayStarColor != value) {
grayStarColor = value;
var col = OwningColumn as DataGridViewRatingColumn;
if (col != null && col.GrayStarColor != value) {
UseColumnStarColor = false;
DataGridView.InvalidateCell(this);
}
}
}
}
//Change the star size via scaling factor (default by 1)
public float StarScale {
get { return starScale; }
set {
if (starScale != value) {
starScale = value;
var col = OwningColumn as DataGridViewRatingColumn;
if (col != null && col.StarScale != value) {
UseColumnStarScale = false;
DataGridView.InvalidateCell(this);
}
}
}
}
public bool UseColumnStarColor { get; set; }
public bool UseColumnStarScale { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
注:该2类DataGridViewRatingColumn和DataGridViewRatingCell应放置在同一个文件,因为我声明了一个静态的内部方法UpdateBrushes中DataGridViewRatingCell,并在课堂上使用它DataGridViewRatingColumn,你可以,如果你想将它们放在不同的文件更改修改.查看提供的属性并使用它们来自定义星星的外观和感觉.它们以不言自明的方式命名.以下是一些显示用法的代码:
dataGridView1.Columns.Add(new DataGridViewRatingColumn(){
//init some properties here ...
});
//To change the ReadOnly which allows user to rate or not, you have to cast
//the column to DataGridViewRatingColumn first, this behavior is caused by
//the failing/abnormal behavior of overriding the ReadOnly (I had to use new instead).
((DataGridViewRatingColumn)dataGridView1.Columns[0]).ReadOnly = true; (default by false)
//You should also enable DoubleBuffered on your DataGridView to eliminate flicker
typeof(Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic)
.SetValue(dataGridView1, true, null);
Run Code Online (Sandbox Code Playgroud)

| 归档时间: |
|
| 查看次数: |
3120 次 |
| 最近记录: |