webForumDet fria alternativet

linq + dropdownlist

4 svar · 573 visningar · startad av doggelito

doggelitoMedlem sedan juni 20003 076 inlägg
#1

Labbar lite linq så här på kvällskvisten men stötte på en "simpel" fundering direkt!
Har denna kod:

DataContext Data = new DataContext();

        var UsersQuery = from users in Data.Users
                             select new {
                                 ID = users.UserId,
                                 Name = users.FirstName + " " + users.LastName
                             };

        DropDownList1.DataSource = UsersQuery;
        DropDownList1.DataValueField = "ID";
        DropDownList1.DataTextField = "Name";
        DropDownList1.DataBind();

Men hur gör jag för att undvika hårdkodning av DataValueField samt DataTextField?

emissionMedlem sedan dec. 19996 721 inlägg
#2

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)

doggelitoMedlem sedan juni 20003 076 inlägg
#3

Oj, det så avancerat ut! :)
Får ta och syna detta mer grundligt.
Jag tycker ju förståss att man bör kunna få ut namnen direkt ur UsersQuery.
För hovrar man över variabeln i VS så får man bla. upp att den är IQueryable och innehåller anonyma typer: ID och Name.
Så här vore ju önskvärt:

        DropDownList1.DataSource = UsersQuery;
        DropDownList1.DataValueField = UsersQuery.nånting.ID;
        DropDownList1.DataTextField = UsersQuery.nånting.Name;
        DropDownList1.DataBind();
emissionMedlem sedan dec. 19996 721 inlägg
#4

doggelito skrev:

Oj, det så avancerat ut! :)

Det är inte särskilt avancerat, och klassen behöver du bara en gång.

Problemet är att du använder en anonym klass. Kanske skulle det vara bättre att alltid fylla på en icke-anonym klass. Du kan ju använda samma klass överallt där en ListControl ska fyllas på.

public class ValueTextEntry {
    public object Value { get; set; }
    public object Text { get; set; }
}
        
//------------

DataContext Data = new DataContext();

var UsersQuery = from users in Data.Users
					 select new ValueTextEntry{
						 Value = users.UserId,
						 Text = users.FirstName + " " + users.LastName
					 };

DropDownList1.DataSource = UsersQuery;
DropDownList1.DataValueField = "Value";
DropDownList1.DataTextField = "Text";
DropDownList1.DataBind();
doggelitoMedlem sedan juni 20003 076 inlägg
#5

Ah! Fiffigt! :bire

126 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
123 ms — hämta tråd, inlägg och bilagor (db)