我决定重新提出这个问题。这就是......
我有一个XML文件:
<?xml version="1.0" standalone="yes"?>
<GenioCodes>
<Code Layer="BI" Colour="1" />
<Code Layer="BP" Colour="1" />
<Code Layer="BS" Colour="1" />
<Code Layer="C" Colour="1" />
<Code Layer="CC" Colour="1" />
<Code Layer="CR" Colour="1" />
</GenioCodes>
我将其读入DataSet
并在DataSource
对象上将其设为DataGridView
:
m_dataSet.ReadXml(textBoxXML.Text);
m_dataGridView.DataSource = m_dataSet.Tables[0];
DataGridView需要有两列:
第1列:这是默认的string
列,应绑定到图层属性。
第2列:这必须是DataGridViewComboBoxColumn
列,并且应该绑定到颜色属性。
第2列的单元格对象必须是ComboboxColorItem
类型。类:
public class ComboboxColorItem
{
public string Name { get; set; }
public ushort Index { get; set; }
public Color Value { get; set; }
public ComboboxColorItem(string Name, ushort Index, Color Value)
{
this.Name = Name;
this.Index = Index;
this.Value = Value;
}
public override string ToString()
{
return Name;
}
static public ComboboxColorItem Create(ushort iColourIndex)
{
OdCmColor oColour = new OdCmColor();
oColour.setColorIndex(iColourIndex);
ComboboxColorItem oColorItem = new ComboboxColorItem(
oColour.colorNameForDisplay(),
iColourIndex,
Color.FromArgb(oColour.red(), oColour.green(), oColour.blue()));
oColour.Dispose();
return oColorItem;
}
}
因此,正如您所看到的,XML中的Color属性只是一个数字。但我们可以使用静态ComboboxColorItem.Create
方法从中创建一个单元格项。
如何将这些全部放在一起?如何使用我的ComboboxColorItem
创建一个DataGridView,它具有类型为DataGridViewComboBoxColumn的第二列,其单元格值为DataSource
?
注意:如果需要,我可以更改XML文件的结构。
答案 0 :(得分:1)
根据您的问题,我创建了一个使用DataSet的工作考试。 IMO,在ComboBox列中使用原始类型更简单。
GetColorFromCode
应使用OdCmColor
为ComboBox项创建颜色和文本。我无法访问该课程。
此示例缺少自定义单元格绘制
public partial class DgvForm : Form
{
private string xml =
@"<?xml version='1.0' standalone='yes'?>
<GenioCodes>
<Code Layer='BI' Colour='1' Value='qwerty'/>
<Code Layer='BP' Colour='2' />
<Code Layer='BS' Colour='3' Value='Hello'/>
<Code Layer='C' Colour='4' />
<Code Layer='CC' Colour='1' />
<Code Layer='CR' Colour='1' />
</GenioCodes>";
DataSet m_dataSet = new DataSet();
public DgvForm()
{
InitializeComponent();
// reading xml from string
var reader = XmlReader.Create(new StringReader(xml));
m_dataSet.ReadXml(reader);
m_dataGridView.DataSource = m_dataSet.Tables[0];
var column = m_dataGridView.Columns["Colour"];
int idx = column.Index;
// removing text column
m_dataGridView.Columns.RemoveAt(idx);
// adding comboBox column
var cbo = new DataGridViewComboBoxColumn
{
Name = "Colour",
DataPropertyName = "Colour",
};
// unique color codes for comboBox
var colorCodes = m_dataSet.Tables[0].AsEnumerable()
.Select(r => r["Colour"])
.Distinct()
.ToList();
cbo.DataSource = colorCodes;
// restore column in orignal position
m_dataGridView.Columns.Insert(idx, cbo);
m_dataGridView.EditingControlShowing += ComboBoxShowing;
}
/// <summary>
/// Activates custom drawing in comboBoxes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ComboBoxShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (e.Control is ComboBox)
{
ComboBox theCB = (ComboBox)e.Control;
theCB.DrawMode = DrawMode.OwnerDrawFixed;
try
{
theCB.DrawItem -= new DrawItemEventHandler(this.ComboItemDraw);
}
catch { }
theCB.DrawItem += new DrawItemEventHandler(this.ComboItemDraw);
}
}
/// <summary>
/// Custom drawing for comboBox items
/// </summary>
private void ComboItemDraw(object sender, DrawItemEventArgs e)
{
Graphics g = e.Graphics;
Rectangle rDraw = e.Bounds;
rDraw.Inflate(-1, -1);
bool bSelected = Convert.ToBoolean(e.State & DrawItemState.Selected);
bool bValue = Convert.ToBoolean(e.State & DrawItemState.ComboBoxEdit);
rDraw = e.Bounds;
rDraw.Inflate(-1, -1);
if (bSelected & !bValue)
{
g.FillRectangle(Brushes.LightBlue, rDraw);
g.DrawRectangle(Pens.Blue, rDraw);
}
else
{
g.FillRectangle(Brushes.White, e.Bounds);
}
if (e.Index < 0)
return;
string code = ((ComboBox) sender).Items[e.Index].ToString();
Color c = GetColorFromCode(code);
string s = c.ToString();
SolidBrush b = new SolidBrush(c);
Rectangle r = new Rectangle(e.Bounds.Left + 5, e.Bounds.Top + 3, 10, 10);
g.FillRectangle(b, r);
g.DrawRectangle(Pens.Black, r);
g.DrawString(s, Form.DefaultFont, Brushes.Black, e.Bounds.Left + 25, e.Bounds.Top + 1);
b.Dispose();
}
/// <summary>
/// Returns color for a given code
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
private Color GetColorFromCode(string code)
{
switch (code)
{
case "1": return Color.Green;
case "2": return Color.Cyan;
case "3": return Color.Orange;
case "4": return Color.Gray;
}
return Color.Red;
}
}
答案 1 :(得分:0)
尝试遍历每个数据集,然后使用.Rows.Add函数将其绑定到Datagridview ...
//Creates and Adds Rows for all Data
for (int i = 0; i < DataSet.Count; i++)
{
DataGridView.Rows.Add(new object[] { columnArray1[i], columnArray2[i] });
}
答案 2 :(得分:0)
感谢您提供迄今为止提供的答案,我非常感谢他们。
我理解它的方式,您可以将DataGridView
属性AutoGenerateColumns
设置为false
。此属性未在IDE中公开,但可以在代码中使用。
如果该属性设置为 false ,我了解我们可以自行设置DVG列定义,然后只使用DataSet
/ DataSource
组合。所以我希望避免读取数据,然后再次有效地读取数据列(根据当前的答案)。
目前,我已将我的代码简化为手动执行操作。因此:
步骤1 - 初始化DVG:
private void GENIO_Code_Editor_Load(object sender, EventArgs e)
{
try
{
buttonDetect.Enabled = m_dbDatabase != null;
InitColourComboBoxColumn();
dataGridView.Columns.Add("Layer", "Layer");
dataGridView.Columns.Add(cboColumn);
if (textBoxXML.Text != "")
ReadXmlToGrid();
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
第2步: - InitColourComboBoxColumn
方法:
private void InitColourComboBoxColumn()
{
try
{
cboColumn = new DataGridViewComboBoxColumn();
cboColumn.Name = "Colour";
cboColumn.ValueMember = "Name";
List<ushort> listColours = new List<ushort>();
listColours.Add(1);
listColours.Add(2);
listColours.Add(3);
listColours.Add(4);
listColours.Add(5);
listColours.Add(6);
listColours.Add(7);
listColours.Add(8);
listColours.Add(9);
listColours.Add(250);
listColours.Add(251);
listColours.Add(252);
listColours.Add(253);
listColours.Add(254);
listColours.Add(255);
foreach (ushort iColourIndex in listColours)
cboColumn.Items.Add(ComboboxColourItem.Create(iColourIndex));
}
catch(Exception ex)
{
throw ex;
}
}
步骤3:实现Read / Save to XML方法:
private void ReadXmlToGrid()
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(textBoxXML.Text);
XmlNodeList listCodes = doc.SelectNodes("GenioCodes/Code");
foreach (XmlNode oCode in listCodes)
{
int iRow = dataGridView.Rows.Add();
dataGridView.Rows[iRow].Cells["Layer"].Value = oCode.Attributes["Layer"].Value;
ushort iColourIndex = Convert.ToUInt16(oCode.Attributes["Colour"].Value);
ComboboxColourItem ocbItem2 = null;
foreach (ComboboxColourItem ocbItem in cboColumn.Items)
{
if (ocbItem.Index == iColourIndex)
{
ocbItem2 = ocbItem;
break;
}
}
if (ocbItem2 == null)
{
ocbItem2 = ComboboxColourItem.Create(iColourIndex);
cboColumn.Items.Add(ocbItem2);
}
dataGridView.Rows[iRow].Cells["Colour"].Value = ocbItem2;
}
}
catch(Exception ex)
{
throw ex;
}
}
private void SaveGridToXml()
{
XmlDocument doc = new XmlDocument();
XmlElement codes = doc.CreateElement("GenioCodes");
foreach(DataGridViewRow row in dataGridView.Rows)
{
if(row != null && !row.IsNewRow)
{
XmlElement code = doc.CreateElement("Code");
code.SetAttribute("Layer", row.Cells["Layer"].Value.ToString());
String strThisColour = row.Cells["Colour"].Value.ToString();
bool bColourFound = false;
foreach (ComboboxColourItem ocbItem in cboColumn.Items)
{
if (ocbItem.Name == strThisColour)
{
code.SetAttribute("Colour", ocbItem.Index.ToString());
bColourFound = true;
break;
}
}
if(!bColourFound) // This should not happen
code.SetAttribute("Colour", "1"); // 1 is red
codes.AppendChild(code);
}
}
doc.AppendChild(codes);
doc.Save(textBoxXML.Text);
}
就是这样。它按我的需要工作。如果有替代方案我可以做:
m_DataSet.ReadXml("myfile.xml");
m_DataGridView.DataSource = m_DataSource;
m_DataSet.WriteXml("myfile.xml");
它创建了我想要的DVG类型(没有重新读取任何列或删除)然后我在其他答案中很有趣,因为我认为这只是我的问题的解决方法。