code reuse

M

mp

here i am able to make a function that can be reused
only the listview changes,
private void ClearCriteria()
{
ClearListView ( this.lvCriteriaList );
}
private void ClearStockWatchList ( )
{
ClearListView ( this.lvStockWatchList);
}
private void ClearListView(ListView lv)
{
for (int i = 0; i < lv.Items.Count; i++)
{
lv.Items.Checked = false;
}
}

to populate those two listviews however, i have two different functions
the objects filling the listview have different property names
not sure how i can do this with just one function and pass the listviews and
collections in
here's the first one
private void LoadCriteriaListIntoListview(List<Criteria > criterialist)
{
lvCriteriaList.Columns.Add("Criteria");
lvCriteriaList.Columns.Add("Code");
lvCriteriaList.View = View.Details;
lvCriteriaList.CheckBoxes = true;
ListViewItem lvitem;
foreach (Criteria criteria in criterialist)
{
lvitem = lvCriteriaList.Items.Add(new
ListViewItem(criteria.Value));
lvitem.SubItems.Add(criteria.Key);
}
int scrollbarWidth = SystemInformation.VerticalScrollBarWidth;
int borderwidth = SystemInformation.BorderSize.Width;
lvCriteriaList.AutoResizeColumn(0,
ColumnHeaderAutoResizeStyle.ColumnContent);
lvCriteriaList.AutoResizeColumn(1,
ColumnHeaderAutoResizeStyle.HeaderSize);

lvCriteriaList.ClientSize = new
Size(lvCriteriaList.Columns[0].Width
+
lvCriteriaList.Columns[1].Width
+ scrollbarWidth +
(borderwidth * 2), lvCriteriaList.ClientSize.Height);
}
so input arg is List<Criteria >
Criteria has two props, Key and Value
the other listview gets input arg of StockListCollection : List<Stock>
Stock has two props Name and Ticker

so the column headers have to be different
and the object types are different
and the property names are different
and one input is List<object> and the other is a class that derives from
List<object>
i'm not seeing an easy way to get away without two separate routines,
even though they are very similar in the rest of the function

i could factor out the resize code into a function but the filling part i'm
not sure?
thoughts?
thanks
mark
 
M

mp

Peter Duniho said:
here i am able to make a function that can be reused
only the listview changes,
[]

Well, actually. you can get most of the benefit from doing just what you
suggest: factor out the resize code, and the View and CheckBoxes
initialization (though, actually.those can probably be set in the Designer
anyway).

Then you still have two methods, plus a third with the shared stuff.

But if you want an even more general purpose approach, there are ways to
do it. Here are a couple.

1) Use a general-purpose type and require the caller to provide an
enumeration:

private void LoadIntoListView(IEnumerable<ListViewInit> initList,
string itemName, string subItemName)
{
lvCriteriaList.Columns.Add(itemName);
lvCriteriaList.Columns.Add(subItemName);
lvCriteriaList.View = View.Details;
lvCriteriaList.CheckBoxes = true;

foreach (ListViewInit init in initList)
{
ListViewItem lvitem = lvCriteriaList.Items
.Add(new ListViewItem(init.Item));

lvitem.SubItems.Add(init.SubItem);
}

int scrollbarWidth = SystemInformation.VerticalScrollBarWidth;
int borderwidth = SystemInformation.BorderSize.Width;

lvCriteriaList.AutoResizeColumn(0,
ColumnHeaderAutoResizeStyle.ColumnContent);
lvCriteriaList.AutoResizeColumn(1,
ColumnHeaderAutoResizeStyle.HeaderSize);

lvCriteriaList.ClientSize = new Size(
lvCriteriaList.Columns[0].Width +
lvCriteriaList.Columns[1].Width +
scrollbarWidth + (borderwidth * 2),
lvCriteriaList.ClientSize.Height);
}

where:

class ListViewInit
{
public string Item { get; private set; }
public string SubItem { get; private set; }

public ListViewInit(string item, string subItem)
{
Item = item;
SubItem = subItem;
}
}

Then you can call it like this:

LoadIntoListView(criteriaList.Select(criteria =>
new ListViewInit(criteria.Key, criteria.Value)),
"Criteria", "Code");

2) Skip the intermediate class and use projection delegates instead:

private void LoadIntoListView<T>(IEnumerable<T> initList,
string itemName, string subItemName,
Func<T, string> getItem, Func<T, string> getSubItem)
{
lvCriteriaList.Columns.Add(itemName);
lvCriteriaList.Columns.Add(subItemName);
lvCriteriaList.View = View.Details;
lvCriteriaList.CheckBoxes = true;

foreach (T init in initList)
{
ListViewItem lvitem = lvCriteriaList.Items
.Add(new ListViewItem(getItem(init)));

lvitem.SubItems.Add(getSubItem(init));
}

int scrollbarWidth = SystemInformation.VerticalScrollBarWidth;
int borderwidth = SystemInformation.BorderSize.Width;

lvCriteriaList.AutoResizeColumn(0,
ColumnHeaderAutoResizeStyle.ColumnContent);
lvCriteriaList.AutoResizeColumn(1,
ColumnHeaderAutoResizeStyle.HeaderSize);

lvCriteriaList.ClientSize = new Size(
lvCriteriaList.Columns[0].Width +
lvCriteriaList.Columns[1].Width +
scrollbarWidth + (borderwidth * 2),
lvCriteriaList.ClientSize.Height);
}

then you call it like this:

LoadIntoListView(criteriaList, "Criteria", "Code",
item => item.Key, item => item.Value);

These are not the only solutions, but IMHO they are among the ones with
the best mix of being both straight-forward and efficient.

Pete

many thanks,
that's exactly what I was looking for
mark
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top