I have a linq query that selects all textboxes in a placeholder and adds them to a list using a struct. I need to expand this functionality to also take the selectedvalue of a DropDownList I am pretty sure I am doing this wrong, because when I debug the method the lists count is 0.
My own guess is that declaring 2 OfType<>() is wrong, but I am pretty new to linq and I have no idea of how else to do it.
Any help would be awesome! Thanks in advance.
Here's what I have so far:
public struct content
{
    public string name;
    public string memberNo;
    public int points;
    public string carclass;
}
List<content> rows = new List<content>();
protected void LinkButton_Submit_Attendees_Click(object sender, EventArgs e)
{
List<content> rows = PlaceHolder_ForEntries.Controls.OfType<TextBox>().OfType<DropDownList>()
        .Select(txt => new
        {
            Txt = txt,
            Number = new String(txt.ID.SkipWhile(c => !Char.IsDigit(c)).ToArray())
        })
        .GroupBy(x => x.Number)
        .Select(g => new content
        {
            carclass = g.First(x => x.Txt.ID.StartsWith("DropDownlist_CarClass")).Txt.SelectedValue,
            name = g.First(x => x.Txt.ID.StartsWith("TextBox_Name")).Txt.Text,
            memberNo = g.First(x => x.Txt.ID.StartsWith("TextBox_MemberNo")).Txt.Text,
            points = int.Parse(g.First(x => x.Txt.ID.StartsWith("TextBox_Points")).Txt.Text)
        })
        .ToList();
}
Here's the method that creates the controls.
protected void createcontrols()
{
    int count = 0;
    if (ViewState["count"] != null)
    {
        count = (int)ViewState["count"];
    }
    while (PlaceHolder_ForEntries.Controls.Count < count)
    {
        TextBox TextBox_Name = new TextBox();
        TextBox TextBox_MemberNo = new TextBox();
        TextBox TextBox_Points = new TextBox();
        DropDownList DropDownList_CarClass = new DropDownList();
        DropDownList_CarClass.Items.Add("Car1");
        ...
        DropDownList_CarClass.Items.Add("Car2");
        TextBox_Name.Attributes.Add("placeholder", "Navn");
        TextBox_Name.ID = "TextBox_Name" + PlaceHolder_ForEntries.Controls.Count.ToString();
        TextBox_Name.CssClass = "input-small";
        TextBox_MemberNo.Attributes.Add("placeholder", "Medlemsnr.");
        TextBox_MemberNo.ID = "TextBox_MemberNo" + PlaceHolder_ForEntries.Controls.Count.ToString();
        TextBox_MemberNo.CssClass = "input-small";
        TextBox_Points.Attributes.Add("placeholder", "Point");
        TextBox_Points.ID = "TextBox_Points" + PlaceHolder_ForEntries.Controls.Count.ToString();
        TextBox_Points.CssClass = "input-small";
        PlaceHolder_ForEntries.Controls.Add(TextBox_Name);
        PlaceHolder_ForEntries.Controls.Add(TextBox_MemberNo);
        PlaceHolder_ForEntries.Controls.Add(DropDownList_CarClass);
        PlaceHolder_ForEntries.Controls.Add(TextBox_Points);
        PlaceHolder_ForEntries.Controls.Add(new LiteralControl("<br />"));
    }
}
                you can use the Where and check if the instance of object is of type!
List<content> rows = PlaceHolder_ForEntries.Controls.Cast<Control>().Where(c => c is TextBox || c is DropDownList)
        .Select(txt => new
        {
            Txt = txt,
            Number = new String(txt.ID.SkipWhile(c => !Char.IsDigit(c)).ToArray())
        })
        .GroupBy(x => x.Number)
        .Select(g => new content
        {
            carclass = g.First(x => x.Txt.ID.StartsWith("DropDownlist_CarClass")).Txt.SelectedValue,
            name = g.First(x => x.Txt.ID.StartsWith("TextBox_Name")).Txt.Text,
            memberNo = g.First(x => x.Txt.ID.StartsWith("TextBox_MemberNo")).Txt.Text,
            points = int.Parse(g.First(x => x.Txt.ID.StartsWith("TextBox_Points")).Txt.Text)
        })
        .ToList();
                        AppDeveloper is right. OfType<T> filters out all objects of types other than T; so by filtering twice, you effectively eliminate all objects in the list.
If you wanted to wrap this logic (filtering all but two types from a list) into something reusable, nothing's stopping you from implementing your own extension method:
using System.Collections;
public static class EnumerableExtensions
{
    public static IEnumerable OfType<T1, T2>(this IEnumerable source)
    {
        foreach (object item in source)
        {
            if (item is T1 || item is T2)
            {
                yield return item;
            }
        }
    }
}
Including the above class in your project will allow you to write code like this in your application:
var textBoxesAndDropDowns = controls.OfType<TextBox, DropDownList>();
To learn more about extension methods, see the MSDN article on the subject.
Note that since the extension method above "lets in" two different types, the result is still a non-generic IEnumerable sequence. If you wanted to treat the result as a generic sequence (e.g., an IEnumerable<Control>), I would recommend using the Cast<T> extension method:
var filteredControls = controls.OfType<TextBox, DropDownList>().Cast<Control>();
                        I haven't read the question thoroughly, but from what the title implies, you can achieve the behavior with:
var collection = new object[] { 5, "4545",  'd', 54.5 , 576 };
var allowedTypes = new[] { typeof(string), typeof(int) }; 
var result = collection
 .Where(item => allowedTypes.Contains(item.GetType()));
See it in action here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With