0

我有一个 xml 文件,它充当数据表。它保存各种类型的数据。任何列中的数据类型都可能不同。一个例子是:row(1)String, int, date; 行(2)二进制,整数,日期;行(3)字符串,二进制,整数。

这导致了我要解决的问题,如何解析单元格内容并在数据类型为二进制或字节类型的单元格中放置一个按钮。

这很棘手,因为不仅所有单元格内容都是不同类型的,而且单元格不会自动分配给列类型,必须手动完成。

关于如何做到这一点的任何想法?

PS我认为使用CellValidating事件我可能能够获得我想要的行为,但是我不知道如何验证一个字符串实际上是二进制数据......

编辑:好的,所以我决定获得所需结果的最简单方法是让用户选择他们希望记录的数据类型。然后稍后检查每一列中的该数据类型,如果该数据类型存在于列中,则放置一个按钮。

我有一个“TableFactory”类,它使表将被序列化并存储在 xml 中。在这个类中,我添加了一个“ColumnDataTypes”枚举和一个部分来处理我想要允许的类型,现在只有 3 个,Integer、String 和 File(byte[])。这种新方法的问题在于,为了正确存储字节数组,我必须将其转换为 Base64String。然而,这将数据类型更改为字符串而不是字节,这使我再次回到开头......我如何解析列数据并在逻辑上确定它是一个字节数组而不仅仅是一个字符串。一旦我知道它是一个字节数组,我就可以在包含字节数组的单元格中放置一个按钮。有没有人对如何做到这一点有任何想法?

表工厂类:

    using System.Data;
    using System.Xml;
    using System.IO;
    using System.Xml.Serialization;
    using XML_Database.usrctrls;

    namespace XML_Database.data
    {
    public class TableFactory
{
    //string _tableName;
    DataTable _dt;

    //public string TableName { get { return _tableName; } set { _tableName = value; } }

    public TableFactory(string tableName)
    {
        if (this._dt == null)
        {
            this._dt = new DataTable(tableName);
        }
    }

    public DataTable Table
    {
        get { return this._dt; }
        set { this._dt = value; }
    }

    public void NewColumn(string ColumnName, ColumnTypes colType)
    {
        if (!this._dt.Columns.Contains(ColumnName))
        {
            switch (colType)
            {
                case ColumnTypes.String:
                    this._dt.Columns.Add(ColumnName, typeof(String));
                    break;
                case ColumnTypes.Integer:
                    this._dt.Columns.Add(ColumnName, typeof(Int32));
                    break;
                case ColumnTypes.Binary:
                    this._dt.Columns.Add(ColumnName, typeof(Byte[]));
                    break;
            }
        }
    }

    public void DeleteColumn(string ColumnName)
    {
        if (_dt.Columns.Contains(ColumnName))
        {
            _dt.Columns.Remove(ColumnName);
        }
    }

    public void SaveTable(string Path)
    {
        data.encryptFiles._SALT = data.dboptions.Salt();
        data.encryptStrings._SALT = data.dboptions.Salt();
        string tablePath = Path + "\\" + _dt.TableName + ".xml";
        DataSet ds = new DataSet();
        XmlDocument xDoc = new XmlDocument();
        ds.Tables.Clear();
        ds.Tables.Add(_dt.Copy());

        XmlElement xE = (XmlElement)Serialize(ds);
        string strXml = xE.OuterXml.ToString();

        xDoc.LoadXml(strXml);
        xDoc.Save(tablePath);
        if (data.dboptions.DBEncryptionOptions())
        {
            File.Delete(Path + "\\" + _dt.TableName + "_enc.xml");
            data.encryptFiles.EncryptFile(tablePath, tablePath.Replace(".xml", "_enc.xml"), data.encryptStrings.Decrypt(data.dboptions.Pwd(), data.dboptions.Salt()));
        }
    }

    public void LoadTable(string Path)
    {
        string tablePath = Path + "\\" + _dt.TableName + ".xml";
        XmlDocument xDoc = new XmlDocument();
        if (File.Exists(tablePath))
        {
            if (_dt.TableName.Contains("_enc"))
            {
                MemoryStream ms = new MemoryStream();
                data.encryptFiles._SALT = data.dboptions.Salt();
                data.encryptStrings._SALT = data.dboptions.Salt();
                data.encryptFiles.DecryptToMemory(tablePath, out ms, data.encryptStrings.Decrypt(data.dboptions.Pwd(), data.dboptions.Salt()));
                using (ms)
                {
                    xDoc.Load(ms);
                }
                DataSet ds = (DataSet)Deserialize(xDoc.DocumentElement, typeof(DataSet));
                _dt = ds.Tables[0];
            }
            else
            {
                xDoc.Load(tablePath);
                DataSet ds = (DataSet)Deserialize(xDoc.DocumentElement, typeof(DataSet));
                _dt = ds.Tables[0];
            }
        }
    }

    private object Deserialize(XmlElement xmlElement, System.Type type)
    {
        Object transformedObject = null;
        try
        {
            Stream memStream = StringToStream(xmlElement.OuterXml);
            XmlSerializer serializer = new XmlSerializer(type);
            transformedObject = serializer.Deserialize(memStream);
        }
        catch (Exception)
        {

        }
        return transformedObject;
    }

    private Stream StringToStream(string p)
    {
        MemoryStream memStream = null;
        try
        {
            byte[] buffer = Encoding.UTF8.GetBytes(p);
            memStream = new MemoryStream(buffer);
        }
        catch (Exception)
        {

        }
        finally
        {
            memStream.Position = 0;
        }
        return memStream;
    }

    private XmlElement Serialize(object TransformObject)
    {
        XmlElement serializedElement = null;
        try
        {
            MemoryStream memStream = new MemoryStream();
            XmlSerializer serializer = new XmlSerializer(TransformObject.GetType());
            serializer.Serialize(memStream, TransformObject);
            memStream.Position = 0;
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(memStream);
            serializedElement = xDoc.DocumentElement;
        }
        catch (Exception)
        {

        }
        return serializedElement;
    }
}
}

任何帮助是极大的赞赏!:)

编辑:我可以添加图像但不能添加常规文件。理想情况下,添加文件和图像是理想的功能。但到目前为止,只有图像会进入我的字节数组列。如果我将列数据类型更改为字符串并存储转换后的 Base64String,我可以存储文件,但我仍然无法弄清楚如何解析数据以确认它是文件而不仅仅是文本......

编辑:好的,我更接近解决这个问题,但不知道如何克服困难......我可以得到一个按钮来显示,但不在正确的单元格中。这里有更多代码可以帮助任何人帮助我回答这个问题......

private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
    {
        button1.ForeColor = Color.Red;
        try
        {
            for (int i = 0; i < dataGridView1.RowCount; i++)
            {
                foreach (DataGridViewCell cell in dataGridView1.Rows[i].Cells)
                {
                    if (cell.Value != null)
                    {
                        if (TryParseBinary(cell.Value.ToString()))
                        {
                            var buttonCell = new DataGridViewButtonCell();
                            buttonCell.Value = "Export File";
                            buttonCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                            dataGridView1.Rows[i].Cells[cell.ColumnIndex] = buttonCell;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Grid Validation Error: " + ex.Message);
        }
    }

    private bool TryParseBinary(string p)
    {
        try
        {
            string path = "C:\\Temp\\" + DateTime.Now.Ticks.ToString() + ".test";
            byte[] bytes = Convert.FromBase64String(p);
            File.WriteAllBytes(path, bytes);

            //File.Delete(path);
            return true;
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error: " + ex.Message);
            return false;
        }
    }

“TryParseBinary”是问题所在。它需要创建一个有效的文件来返回“true”,但我不确定如何让它足够聪明来判断它刚刚写的是否是一个有效的文件......

4

1 回答 1

0

好的,所以我能够为我的问题创建一个解决方案。这不完全是我想要的,但它确实完成了工作。我为我的 datagridview 使用“DragDrop”方法检查数据表中是否存在“文件”和“MIME”列。然后,如果它们不存在,我将创建这些列,如果存在,我将转换为 Base64String 的文件字节添加到“文件”列,并将文件扩展名添加到“MIME”列。然后我让“RowsAdded”事件将“文件”单元格更改为按钮。但是目前它没有保留文本“导出文件”,但我会继续努力,这似乎是一个简单的修复。下面是我的代码:

    private void dataGridView1_DragDrop(object sender, DragEventArgs e)
    {
        try
        {
            Point cursorPosition = dataGridView1.PointToClient(Cursor.Position);
            DataGridView.HitTestInfo info = dataGridView1.HitTest(cursorPosition.X, cursorPosition.Y);
            tableFactory = new data.TableFactory(TablesDropDown.SelectedValue.ToString());
            tableFactory.LoadTable(dbPath);

            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

                foreach (DataColumn col in tableFactory.Table.Columns)
                {
                    if (col.ColumnName != "MIME" && col.ColumnName != "File")
                    {
                        tableFactory.NewColumn("MIME", ColumnTypes.String);
                        tableFactory.NewColumn("File", ColumnTypes.String);
                        tableFactory.SaveTable(dbPath);
                        ColumnsDataGrid();

                        dataGridView1.Rows[info.RowIndex].Cells["File"].Value = Convert.ToBase64String(GetFile(files));
                        FileInfo f = new FileInfo(files[0]);
                        dataGridView1.Rows[info.RowIndex].Cells["MIME"].Value = f.Extension;
                    }
                    else
                    {
                        dataGridView1.Rows[info.RowIndex].Cells["File"].Value = Convert.ToBase64String(GetFile(files));
                        FileInfo f = new FileInfo(files[0]);
                        dataGridView1.Rows[info.RowIndex].Cells["MIME"].Value = f.Extension;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("This was not a valid file to store in the database. Error Msg: " + ex.Message);
        }
    }


    private byte[] GetFile(string[] files)
    {
        byte[] bytes = null;
        foreach (string file in files)
        {
            FileInfo fileInfo = new FileInfo(file);
            if (File.Exists(file))
            {
                bytes = File.ReadAllBytes(file);
            }
        }
        return bytes;
    }


    private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
    {
        button1.ForeColor = Color.Red;
        try
        {
            for (int i = 0; i < dataGridView1.RowCount; i++)
            {
                foreach (DataGridViewColumn col in dataGridView1.Columns)
                {
                    if (col.Name == "File")
                    {
                        var buttonCell = new DataGridViewButtonCell();
                        buttonCell.Value = "Export File";
                        buttonCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                        dataGridView1.Rows[i].Cells[col.Index] = buttonCell;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Grid Validation Error: " + ex.Message);
        }
    }

如果您看到需要调整或可以做得更好的东西,我愿意接受建议!:)

于 2013-01-16T17:43:53.903 回答