2011-08-09 17 views
0

我在綁定到BindingList的Win Forms應用程序中使用DataGridView,並且希望改進業務的「分離」 - 邏輯和演示。如何自定義DataGridView基於網格綁定到的BindingList <T>的單元格

在我的Form_Load事件,我所說的程序來建立的BindingList,然後我設置DGV的.DataSource本的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個語句打擾我;正如你所看到的,我希望對從「行」和「消息」屬性創建的列進行較小的修改。它感覺很臭,我應該在最後2行中硬編碼自定義對象的屬性。

是否會有一種更加優雅的定製這兩列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)); 
     } 
    } 
} 

}

}

回答

0

我實在不明白這是要替代的解決方案比你提供的更容易。您不應該將某種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); 

}