Det kan man inte undvika (jo, med reflection borde det gå), men en variant som jag totade ihop pre-Linq (just för att lösa det typiska FirstName+LastName-problemet i en dropdown) löser båda dina "problem"
public class ValueTextList<T> : IEnumerable
{
public delegate string ValueDelegate(T t);
IEnumerable<T> _list;
ValueDelegate _valueDelegate;
ValueDelegate _textDelegate;
public ValueTextList(IEnumerable<T> list,ValueDelegate valueDelegate,ValueDelegate textDelegate)
{
_list = list;
_valueDelegate = valueDelegate;
_textDelegate = textDelegate;
}
public IEnumerator GetEnumerator()
{
return new ValueTextEnumerator(this);
}
public class ValueTextEntry //Samma som Pair, men tydligare namn
{
object _value,_text;
public ValueTextEntry(string value, string text)
{
_value = value;
_text = text;
}
public string Text
{
get
{
return _text;
}
}
public string Value
{
get
{
return _value;
}
}
}
private class ValueTextEnumerator : IEnumerator
{
IEnumerator<T> _enumerator;
ValueTextList<T> _list;
public ValueTextEnumerator(ValueTextList<T> list)
{
_enumerator = list._list.GetEnumerator();
_list = list;
}
public object Current
{
get {
string value = _list._valueDelegate(_enumerator.Current);
string text = _list._textDelegate(_enumerator.Current);
return new ValueTextEntry(value, text);
}
}
public bool MoveNext()
{
return _enumerator.MoveNext();
}
public void Reset()
{
_enumerator.Reset();
}
}
}
Med denna klass kan man lösa bindningen så här:
DropDownList1.DataValueField = "Value";
DropDownList1.DataTextField = "Text";
DropDownList1.DataSource = new ValueTextList<User>(
Data.Users,
delegate(User p)
{
return p.FirstName;
},
delegate(User p)
{
return string.Format("{0} {1}", p.FirstName, p.LastName);
}
);
DropDownList1.DataBind();
Självklart kan man göra koden mer eller mindre generisk (som i Generic)