【问题标题】:Reordering DatagridViews Columns and Saving the new Position Programmatically重新排序 DatagridViews 列并以编程方式保存新位置
【发布时间】:2017-03-25 08:40:50
【问题描述】:

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

【问题讨论】:

  • 请提供更多信息例如:您尝试过什么来保存用户希望使用的设计?
  • 我还没有尝试过任何东西。我不知道如何实现这一点。将属性“AllowUserToOrderColumns”设置为 true 允许我在运行时更改列索引。但这并没有改变列索引永久

标签: c# winforms datagrid


【解决方案1】:

也许是一个老问题,但我想出了一些我认为更简单的问题。

首先,在表单类的开头,添加以下字段:

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
}

【讨论】:

  • 这是一个很好的例子。谢谢你的代码。很有帮助。
【解决方案2】:

实体:

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;
            }
    }
}

我的 Form1 用于测试:

        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 文件中。您可以通过实现自定义保存和加载方法轻松扩展/修改它。

【讨论】:

    【解决方案3】:

    这可能会帮助你

    公共部分类 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 { }
        }
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 2019-10-09
      • 1970-01-01
      相关资源
      最近更新 更多