重新排序DatagridViews列和保存新的位置编程

本文关键字:保存 位置 编程 DatagridViews 新排序 排序 | 更新日期: 2023-09-27 18:17:29

我有一个datagridview在我的Windows窗体。我需要允许用户重新排序列,然后永久保存更改。我设置myGrid。AllowUserToOrderColumns = true;但是这只会改变design上的显示索引

重新排序DatagridViews列和保存新的位置编程

可能是一个老问题,但我想到了一些我认为更简单的问题。

首先,在表单类的开头添加以下字段:
public partial class MyForm : Form
{
    //So whenever you change the filename, you write it once, 
    //everyone will be updated
    private const string ColumnOrderFileName = "ColumnOrder.bin";
    //To prevent saving the data when we don't want to
    private bool refreshing = false;
    ... // the rest of your class

然后,使用以下方法附加到事件ColumnDisplayIndexChanged:

private void MyDataGridView_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
{
    //Because when creating the DataGridView, 
    //this event will be raised many times and we don't want to save that
    if (refreshing)
        return;
    //We make a dictionary to save each column order along with its name
    Dictionary<string, int> order = new Dictionary<string, int>();
    foreach (DataGridViewColumn c in dgvInterros.Columns)
    {
        order.Add(c.Name, c.DisplayIndex);
    }
    //Then we save this dictionary
    //Note that you can do whatever you want with it...
    using (FileStream fs = new FileStream(ColumnOrderFileName, FileMode.Create))
    {
        IFormatter formatter = new BinaryFormatter();
        formatter.Serialize(fs, order);
    }
}

然后是OrderColumns方法:

private void OrderColumns()
{
    //Will happen the first time you launch the application,
    // or whenever the file is deleted.
    if (!File.Exists(ColumnOrderFileName))
        return;
    using (FileStream fs = new FileStream(ColumnOrderFileName, FileMode.Open))
    {
        IFormatter formatter = new BinaryFormatter();
        Dictionary<string, int> order = (Dictionary<string, int>)formatter.Deserialize(fs);
        //Now that the file is open, we run through columns and reorder them
        foreach (DataGridViewColumn c in MyDataGridView.Columns)
        {
            //If columns were added between two versions, we don't bother with it
            if (order.ContainsKey(c.Name))
            {
                c.DisplayIndex = order[c.Name];
            }
        }
    }
}

最后,当你填充你的DataGridView时:

private void FillDataGridView()
{
    refreshing = true; //To prevent data saving while generating the columns
    ... //Fill you DataGridView here            
    OrderColumns(); //Reorder the column from the file
    refreshing = false; //Then enable data saving when user will change the order
}

实体:

public class Customer : INotifyPropertyChanged
{
    string _firstname = "";
    public string Firstname
    {
        get { return _firstname; }
        set { _firstname = value; OnPropertyChanged("Firstname"); }
    }
    string _lastname = "";
    public string Lastname
    {
        get { return _lastname; }
        set { _lastname = value; OnPropertyChanged("Lastname"); }
    }
    int _age = 0;
    public int Age
    {
        get { return _age; }
        set { _age = value; OnPropertyChanged("Age"); }
    } 
    public Customer()
    {
    }
    protected void OnPropertyChanged(string name)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(name));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

可序列化代理:

[Serializable]
public class DataGridViewColumnProxy
{
    string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
    int _index;
    public int Index
    {
        get { return _index; }
        set { _index = value; }
    }
    public DataGridViewColumnProxy(DataGridViewColumn column)
    {
        this._name = column.DataPropertyName;
        this._index = column.DisplayIndex;
    }
    public DataGridViewColumnProxy()
    {
    }
}
[Serializable]
public class DataGridViewColumnCollectionProxy
{
    List<DataGridViewColumnProxy> _columns = new List<DataGridViewColumnProxy>();
    public List<DataGridViewColumnProxy> Columns
    {
        get { return _columns; }
        set { _columns = value; }
    }
    public DataGridViewColumnCollectionProxy(DataGridViewColumnCollection columnCollection)
    {
        foreach (var col in columnCollection)
        {
            if (col is DataGridViewColumn)
                _columns.Add(new DataGridViewColumnProxy((DataGridViewColumn)col));
        }
    }
    public DataGridViewColumnCollectionProxy()
    {
    }
    public void SetColumnOrder(DataGridViewColumnCollection columnCollection)
    {
        foreach (var col in columnCollection)
            if (col is DataGridViewColumn)
            {
                DataGridViewColumn column = (DataGridViewColumn)col;
                DataGridViewColumnProxy proxy = this._columns.FirstOrDefault(p => p.Name == column.DataPropertyName);
                if (proxy != null)
                    column.DisplayIndex = proxy.Index;
            }
    }
}

My Form1 for testing:

        public partial class Form1 : Form
{
    BindingSource _customers = GetCustomerList();
    public BindingSource Customers
    {
        get { return _customers; }
        set { _customers = value; }
    }
    public Form1()
    {
        InitializeComponent();
        dataGridView1.DataSource = Customers;
        LoadDataGridOrderFromFile("myDataGrid.xml", dataGridView1.Columns);
    }
    private static BindingSource GetCustomerList()
    {
        BindingSource customers = new BindingSource();
        customers.Add(new Customer() { Firstname = "John", Lastname = "Doe", Age = 28 });
        customers.Add(new Customer() { Firstname = "Joanne", Lastname = "Doe", Age = 25 });
        return customers;
    }
    static object fileAccessLock = new object();
    private static void SaveDataGridOrderToFile(string path, DataGridViewColumnCollection colCollection)
    {
        lock (fileAccessLock)
        using (FileStream fs = new FileStream(path, FileMode.Create))
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(DataGridViewColumnCollectionProxy));
            xmlSerializer.Serialize(fs, new DataGridViewColumnCollectionProxy(colCollection));
        }
    }
    private static void LoadDataGridOrderFromFile(string path, DataGridViewColumnCollection colCollection)
    {
        if (File.Exists(path))
        {
            lock (fileAccessLock)
                using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(DataGridViewColumnCollectionProxy));
                DataGridViewColumnCollectionProxy proxy = (DataGridViewColumnCollectionProxy)xmlSerializer.Deserialize(fs);
                proxy.SetColumnOrder(colCollection);
            }
        }
    }
    private void dataGridView1_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
    {
        SaveDataGridOrderToFile("myDataGrid.xml", dataGridView1.Columns);
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.ColumnDisplayIndexChanged +=dataGridView1_ColumnDisplayIndexChanged;
    }
}

它将保存DataPropertyName和DisplayIndex到xml文件中。您可以通过实现您的自定义保存和加载方法轻松地扩展/修改它,以存储数据。

这可能对你有帮助

public partial class Form1: Form{

public Form1()
{
   InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
   m_Grid.AllowUserToOrderColumns = true;
   SetDisplayOrder();
}
private void OnFormClosing(object sender, FormClosingEventArgs e)
{
   CacheDisplayOrder();
}
private void CacheDisplayOrder()
{
   IsolatedStorageFile isoFile =
      IsolatedStorageFile.GetUserStoreForAssembly();
   using (IsolatedStorageFileStream isoStream = new
      IsolatedStorageFileStream("DisplayCache", FileMode.Create,
         isoFile))
   {
      int[] displayIndices =new int[m_Grid.ColumnCount];
      for (int i = 0; i < m_Grid.ColumnCount; i++)
      {
         displayIndices[i] = m_Grid.Columns[i].DisplayIndex;
      }
      XmlSerializer ser = new XmlSerializer(typeof(int[]));
      ser.Serialize(isoStream,displayIndices);
   }
}
private void SetDisplayOrder()
{
   IsolatedStorageFile isoFile =
      IsolatedStorageFile.GetUserStoreForAssembly();
   string[] fileNames = isoFile.GetFileNames("*");
   bool found = false;
   foreach (string fileName in fileNames)
   {
      if (fileName == "DisplayCache")
         found = true;
   }
   if (!found)
      return;
   using (IsolatedStorageFileStream isoStream = new
      IsolatedStorageFileStream("DisplayCache", FileMode.Open,
         isoFile))
   {
      try
      {
         XmlSerializer ser = new XmlSerializer(typeof(int[]));
         int[] displayIndicies =
            (int[])ser.Deserialize(isoStream);
         for (int i = 0; i < displayIndicies.Length; i++)
         {
            m_Grid.Columns[i].DisplayIndex = displayIndicies[i];
         }
      }
      catch { }
    }
}

}