Skip to main content
Code Review

Return to Question

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

In the process of getting this question this question answered, I realized I needed to separate my column-generation logic from the data population. This led to the need to preserve the ColumnDataBuilder<TDATA> builder object that I used to create the columns, so that I could keep track of the type of my data.

In the process of getting this question answered, I realized I needed to separate my column-generation logic from the data population. This led to the need to preserve the ColumnDataBuilder<TDATA> builder object that I used to create the columns, so that I could keep track of the type of my data.

In the process of getting this question answered, I realized I needed to separate my column-generation logic from the data population. This led to the need to preserve the ColumnDataBuilder<TDATA> builder object that I used to create the columns, so that I could keep track of the type of my data.

Source Link
Bobson
  • 1k
  • 5
  • 13

Generic data for ListView

I'm in the midst of writing a custom ListView for our application.

In the process of getting this question answered, I realized I needed to separate my column-generation logic from the data population. This led to the need to preserve the ColumnDataBuilder<TDATA> builder object that I used to create the columns, so that I could keep track of the type of my data.

Ideally, usage will look something like this:

builder = MyListView.ColumnsFor<ReceiptHeaderForShipping>();
 mlvShippingList.createColumns(_builder.Create("Receipt", 60, x => x.receiptNumber),
 _builder.Create("Cust", 100, x => x.customer.LastName + ", " + x.customer.FirstName),
 _builder.Create("Total", 60, MyListView.ColumnType.Currency, x => x.subTotal)
);

And then later

mlvShippingList.populateData(_builder, data);

In addition, the MyListView will have to know what type of data it was built with, in order to know what type of ColumnDataBuilder the IMyColumnData comes from, so that it can cast to it in order to sort.


From MyListView:

public partial class MyListView : ListView
{
 public static ColumnDataBuilder<T> ColumnsFor<T>(IEnumerable<T> data)
 {
 return new ColumnDataBuilder<T>();
 }
 public void populateFromData<TDATA>(IEnumerable<TDATA> data, params ColumnDataBuilder<TDATA>.IMyListViewColumnData[] columns)
 {
 createColumns(columns);
 populateData(data, columns);
 }
 public void createColumns<TDATA>(params ColumnDataBuilder<TDATA>.IMyListViewColumnData[] columns)
 {
 Columns.Clear();
 foreach (var col in columns)
 {
 var ch = new ColumnHeader
 {
 Text = col.Name,
 Width = col.Width,
 Tag = col,
 };
 // Other formatting goes here
 this.Columns.Add(ch);
 }
 }
 private void populateData<TDATA>(IEnumerable<TDATA> data, params ColumnDataBuilder<TDATA>.IMyListViewColumnData[] columns)
 {
 Items.Clear();
 var parsedData = data.Select(row => CreateListViewItem(columns, row));
 this.Items.AddRange(parsedData.ToArray());
 }
 public class ColumnDataBuilder<T>
 {
 internal List<IMyListViewColumnData> columns = new List<IMyListViewColumnData>(); 
 public interface IMyListViewColumnData
 {
 string Name { get; }
 int Width { get; }
 ColumnType Type { get; }
 string GetDataString(T dataRow);
 }
 public delegate TOut FormatData<out TOut>(T dataIn);
 public class MyListViewColumnData<TOut> : IMyListViewColumnData
 {
 public string Name { get; private set; }
 public int Width { get; private set; }
 public ColumnType Type { get; private set; }
 private readonly FormatData<TOut> _dataFormatter;
 public MyListViewColumnData(string name, int width, ColumnType type, FormatData<TOut> dataFormater)
 {
 _dataFormatter = dataFormater;
 Type = type;
 Width = width;
 Name = name;
 }
 public string GetDataString(T dataRow)
 {
 object data = _dataFormatter(dataRow);
 switch (Type)
 {
 case ColumnType.String:
 case ColumnType.Integer:
 case ColumnType.Decimal:
 return data.ToString();
 case ColumnType.Date:
 return ((DateTime)data).ToShortDateString();
 case ColumnType.Currency:
 return ((decimal)data).ToString("c");
 case ColumnType.Boolean:
 return (bool)data ? "Y" : "N";
 default:
 throw new ArgumentOutOfRangeException();
 }
 }
 }
 #region Factory Methods
 public IMyListViewColumnData Create<TOut>(string name, int width, ColumnType type, FormatData<TOut> dataFormater)
 {
 var col = new MyListViewColumnData<TOut>(name, width, type, dataFormater);
 columns.Add(col);
 return col;
 }
 public IMyListViewColumnData Create(string name, int width, FormatData<DateTime> dataFormater)
 {
 return Create(name, width, ColumnType.Date, dataFormater);
 }
 // More type-specific factories go here
 #endregion
 }
}

Am I totally off base at this point? Is this a reasonable track to go down?

lang-cs

AltStyle によって変換されたページ (->オリジナル) /