Как настроить ячейку DataGridView на основе BindingList <T>, к которому привязана сетка - PullRequest
0 голосов
/ 09 августа 2011

Я использую DataGridView в приложении Win Forms, которое привязано к BindingList, и я хотел бы улучшить "разделение" бизнес-логики и представления.

В моем событии Form_Load я вызываю подпрограмму для создания BindingList, а затем я устанавливаю .DataSource DGV в этот BindingList:

private void initializeFileList(string rootFolder) // populate grid with .xml filenames to be processed
    {
        String root = rootFolder;
            var result = Directory.GetFiles(root, "*.xml", SearchOption.AllDirectories)
                    .Select(name => new InputFileInfo(name))
                    .ToList();
            _filesToParse =  new BindingList<InputFileInfo>(result.ToList());
            dataGridView1.DataSource = _filesToParse;
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
            dataGridView1.Columns["Rows"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            dataGridView1.Columns["Message"].DefaultCellStyle.ForeColor = Color.Red;

Это последние 2 утверждения, которые беспокоят меня; как видите, я хочу незначительных косметических изменений в столбцах, созданных из свойств «Rows» и «Message». Воняет, что я должен жестко задавать свойства моего пользовательского объекта в этих последних двух строках.

Был бы более элегантный способ настройки этих двух столбцов DGV - с целью полного использования привязки, предоставляемой: dataGridView1.DataSource = _filesToParse; Другими словами, по-прежнему настраивать столбцы но делайте это из чего-то в «деловом» объекте, а не из текущей техники.

Вот мой InputFileInfo класс (из другого проекта в том же решении):

namespace CBMI.Common
{
public class InputFileInfo : INotifyPropertyChanged
{
    private bool processThisFile;
    public bool Process
    {
        get { return processThisFile; }
        set
        {
            Utilities.Set(this, "Process", ref processThisFile, value, PropertyChanged);
        }
    }
    public string FileName { get; set; }
    private long rowsReturned;
    public long Rows
    {
        get { return rowsReturned; }
        set
        {
            Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged);
        }
    }
    private string message;
    public string Message
    {
        get { return message; }
        set
        {
            Utilities.Set(this, "Message", ref message, value, PropertyChanged);
        }
    }
    // constructor
    public InputFileInfo(string fName)
    {
        Process = true;
        FileName = fName;
        Rows = 0;
        Message = String.Empty;
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
public static class Utilities
{
public static void Set<T>(object owner, string propName,
    ref T oldValue, T newValue, PropertyChangedEventHandler eventHandler)
{
    // make sure the property name really exists
    if (owner.GetType().GetProperty(propName) == null)
    {
    throw new ArgumentException("No property named '" + propName + "' on " + owner.GetType().FullName);
    }
    // we only raise an event if the value has changed
    if (!Equals(oldValue, newValue))
    {
        oldValue = newValue;
        if (eventHandler != null)
        {
        eventHandler(owner, new PropertyChangedEventArgs(propName));
        }
    }
}

}

}

1 Ответ

0 голосов
/ 09 августа 2011

Я не вижу альтернативного решения, которое будет проще, чем то, что вы предоставили.Вы не должны смешивать какой-то CellStyle с вашим объектом, связанным с данными, так как это не очень хорошая практика.

Единственное, что я бы предложил, это отключить AutoGenerateColumns и определить свой собственный стиль:

private static void AdditionalInitialization(DataGridView dgv, object dataSource) {

 dgv.AutoGenerateColumns = false;
 dgv.DataSource = dataSource; // Needs to occur after the auto generate columns is set to off
 DataGridViewTextColumn msgCol = new DataGridViewTextColumn();
 msgCol.HeaderText = "Message";
 msgCol.DataPropertyName = "Message";
 msgCol.DefaultCellStyle.ForeColor = Color.Red;
 dgv.Columns.Add(msgCol);
}

Этот метод может быть помещен в любой из ваших классов, поскольку он статический, т.е. ваш InputFileInfo.cs

Затем, когда ваша форма загружается, сделайте следующее:

private void initializeFileList(string rootFolder) // populate grid with .xml filenames to be processed
{
    String root = rootFolder;
        var result = Directory.GetFiles(root, "*.xml", SearchOption.AllDirectories)
                .Select(name => new InputFileInfo(name))
                .ToList();
        _filesToParse =  new BindingList<InputFileInfo>(result.ToList());
        InputFileInfo.AdditionalInitialization(datagridview1,_filesToParse);

}

...