I have 2 StringCollections:
StringCollection ParameterIDs
StringCollection ParameterValues
Is it able to map these both StringCollections as DataSource, something like:
repeater.DataSource = ParameterIDs (as row1) + ParameterValues (as row2);
repeater.DataBind();
and use them in repeater like:
<asp:Repeater ID="repeatParameters" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td class="formLabel">
<asp:Label ID="lblParameterID" Text="<% #DataBinder.Eval(Container.DataItem,"ParameterIDs") %>" runat="server" MaxLength="50"></asp:Label><br />
</td>
<td class="formInputText">
<asp:Label ID="lblParameterValue" Text="<%#DataBinder.Eval(Container.DataItem,"ParameterValues") %>" runat="server" MaxLength="50"></asp:Label><br />
</td>
</tr>
<tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
First thought:
Mash them up in a Dictionary and use that as a datasource.
Second thought:
Create a DataSet with the values you need.
Third thought:
Use KeyValuePair.
As you see there are a lot of different ways of doing this but all of them share a common element:
Create a single object which stores and maps the corresponding values.
No, because the DataSource requires an object with the ICollection interface.
Like the others said, you could create a dictionary or something like:
List<KeyValuePair<string,string>>
Where the parameter id is the key, and the parameter value is the value in the KeyValuePair.
This will do exactly what you want, providing you are using .NET 3.5:
StringCollection parameterIds = new StringCollection();
StringCollection parameterValues = new StringCollection();
parameterIds.Add("someID");
parameterValues.Add("someValue");
var dataSource = parameterIds.Cast<string>()
.SelectMany(itemOne => parameterValues
.Cast<string>(), (itemOne, item2) => new { Row1 = itemOne, Row2 = item2 });
repeater.DataSource = dataSource;
repeater.DataBind();
Like Bogdan_Ch has said, I recommend you move away from StringCollection to List<string> if you are using .NET 2.0 and above. Doing that has the added advantage that you don't need to use the Cast extension method.
I would populate a Dictionary with your string collections and then bind to the Dictionary.
I would suggest 2 options
1. In .NET 1.1 you don't have generic lists, so you may join collections manually in your code, and then use joined collectionas a datasource
StringCollection joined = new StringCollection();
foreach(string s in stringCollection1)
joined.Add(s);
foreach (string s in stringCollection2)
{
if (!joined.Contains(s))
joined.Add(s);
}
In .NET 2.0 and more I would suggest you to use List instead of StringCollection
With AddRange() you can add another list to an existing list.
In .NET 3.5 you can use Linq to intersect 2 lists
public static IEnumerable<TSource> Intersect<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second
)
Related
I am populating a div with many usercontrols, right now they are being added in the order that they are being read from the db. The UserControls markup looks like this:
<div class="Content_Thumb">
<div class="Video_pic">
<a href="tutorialname.aspx">
<asp:Label ID="TutInfo" CssClass="CoverLbl_top" runat="server" Text="Label"></asp:Label>
<asp:Label ID="TutInfo2" CssClass="CoverLbl_bottom" runat="server" Text="Description..."></asp:Label>
<asp:Image ID="ThumbPic" CssClass="Thumb_Pic" runat="server" ImageUrl="/Images/Video_Thumb.png" />
</a>
</div>
<div class="Thumb_Info">
<asp:Label ID="Views" CssClass="ViewsLbl" runat="server" Text="680"></asp:Label>
<asp:Label ID="Comments" CssClass="CommentsLbl" runat="server" Text="11"></asp:Label>
<asp:Label ID="Likes" CssClass="LikesLbl" Style="TEXT-ALIGN: right" runat="server" Text="133"></asp:Label>
</div>
<div class="Thumb_Border">
<asp:Image ID="UserPic" CssClass="Thumb_UploaderPic" runat="server" ImageUrl="/Images/Profile_Placeholder.png" />
<a href="google.com">
<asp:Label ID="UserLbl" CssClass="Thumb_UploaderInfo" runat="server" Text="Label"></asp:Label>
</a>
</div>
Then i've got these properties that are bound to the labels (some removed since i dont want to clutter the post).
public string TutorialInfo
{
get;
set;
}
public int TutorialViews
{
get;
set;
}
public override void DataBind()
{
TutInfo.Text = TutorialInfo;
Views.Text = TutorialViews.ToString();
Comments.Text = TutorialComments.ToString();
Likes.Text = TutorialLikes.ToString();
UserLbl.Text = TutorialUploader;
base.DataBind();
}
Now, what I want to do with these controls are to sort them by the property values. (highest number of views loads first etc). I'm currently at the stage where i've added them to a list, and now I'm trying to sort that list using LINQ's OrderBy like I saw on a post here.
List<UserControl> controls = new List<UserControl>();
foreach (var Tutorial in dataconnection.Tutorial)
{
var control = LoadControl("~/WebUserControl1.ascx") as WebUserControl1;
control.TutorialInfo = Tutorial.Title;
control.TutorialComments = (int)Tutorial.Comments;
control.TutorialViews = (int)Tutorial.Views;
control.TutorialLikes = (int)Tutorial.Likes;
control.TutorialUploader = Tutorial.Uploader;
control.DataBind();
//base.OnPreRender(e);
ThumbTest.Controls.Add(control);
controls.Add(control);
var testcount = controls.Count();
control.Visible = false;
}
var SortedList = controls.OrderBy(o => o.TutorialViews).ToList();
However i'm not able to access the properties even though they are public? "o.TutorialViews" is throwing an error. So how can i sort these controls?
I'm Fairly new to programming in general so my apologies if this turns out to be a silly mistake.
TLDR: How do I sort Usercontrols by property value.
Your list is a list of UserControl objects, which is the generic user control provided by ASP.NET:
List<UserControl> controls = new List<UserControl>();
The UserControl object doesn't have a property called TutorialViews, so you can't access that property on that type. However, you're adding custom user controls to the list:
var control = LoadControl("~/WebUserControl1.ascx") as WebUserControl1;
If every item in the list is going to be of type WebUserControl1 then you can declare the list itself with that type:
List<WebUserControl1> controls = new List<WebUserControl1>();
Since WebUserControl1 does define that property, you'll be able to access it.
Another approach might be to cast it when you access it, like this:
controls.OrderBy(o => ((WebUserControl1)o).TutorialViews)
But that's kind of messy and shouldn't be necessary. It's better to use the correct type in the first place.
Essentially, this is a symptom of the statically typed nature of C# (and many other languages). Type B inherits from Type A, so every instance of B is an instance of A. But not every instance of A is an instance of B, so you can't call a B property on an instance of A.
Think of an analogy... You have a list of Shape objects, and you populate it with Circle objects. This works, because Circles are Shapes. But then you try to access the Radius property on an element in that list, and you get an error. This is because it's a list of Shapes and not every shape has a Radius. You'd need to either make it a list of Circles or cast that element to a Circle for the compiler to know that there's a Radius.
For lots of further reading on the subject, take a look at Polymorphism and the Liskov Substitution Principle.
I have listview and String array datasource. How can I bind them using eval ?
<telerik:RadListView ID="lvDevSampTableSelection" runat="server" AllowMultiItemSelection="true">
<ItemTemplate>
<p><%# Eval("??") %></p>
</ItemTemplate>
</telerik:RadListView>
here is code behind
ResultDto<String[]> result = client.GetTableNames("IMAPPUSER");
var source = new BindingSource();
source.DataSource = result.Data;
lvDevSampTableSelection.DataSource = source;
lvDevSampTableSelection.DataBind();
I use <%# Container.DataItem %> instead of eval and get data from string to listview
You can't, it needs to evaluate field names from the object that is the datasource (be it columns in datatable or fields in some List). Thus, I think your best option is to create a custom class with a couple of fields, create a List<> from that class and bind to that list.
I am new to linq. I am using linq to get vlaues from datalist control and creating a datatable with that values. The datatable contains three columns. In that, sometimes the 'Answer' column is having a data which is comma separated.
DataTable SaveAnswer = clsSource.SetData();
var df = from DataListItem dli in PollDataList.Items
let z = ((HiddenField)dli.FindControl("IDReqHiddenField"))
let y = ((RadioButtonList)dli.FindControl("rdblstPollOptions"))
let v = ((CheckBoxList)dli.FindControl("CheckBoxListMultiplePollOptions"))
select new
{
PollId=z.Value,
Answered1 = y.SelectedValue,
Answered2=v.Items.Cast<ListItem>().Where(r=>r.Selected)
};
var result = from p in df
select SavePollAnswer.LoadDataRow(
new object[] {
p.PollId,p.Answered1+string.Join( ", ", p.Answered2 ),""
},
false);
SavePollAnswer = result.CopyToDataTable();
And here is my design
<asp:DataList ID="PollDataList" runat="server" CssClass="poll-preview">
<ItemTemplate>
<asp:HiddenField ID="PollIDReqHiddenField" Value='<%# Eval("PollID") %>' runat="server" Visible="false" />
<asp:Label ID="lblReqQuestionNumber" runat="server" Text='<%# Eval("NoofPollQuestion") %>' Font-Bold="true"></asp:Label><br />
<asp:Label ID="lblRequiredPollQusetion" runat="server" Text='<%# Eval("PollQuestions") %>' Font-Bold="false"></asp:Label>
<asp:Label ID="lblReqNotification" runat="server" ForeColor="Red" CssClass='<%# Eval("PollReq") %>' Text="*" Font-Bold="true"></asp:Label>
<asp:RadioButtonList ID="rdblstPollOptions" DataSource='<%# Eval("PollOptionsReq") %>' runat="server"></asp:RadioButtonList>
<asp:CheckBoxList ID="CheckBoxListMultiplePollOptions" DataSource='<%# Eval("PollOptionsMul") %>' runat="server" RepeatDirection="Vertical" RepeatColumns="1"></asp:CheckBoxList>
</ItemTemplate>
</asp:DataList>
But we want the datatable output like this
Thanks in advance!
LINQ can get you partway by allowing you to nest from clauses in queries (simplifying the output a bit):
from DataListItem dli in PollDataList.Items
let z = ... // as in existing code
let y = ...
let v = ...
from checkbox in v.Items
where checkbox.Selected
select new [] { z.Value, checkbox.Value, "" }
Here you will get an output item for each selected checkbox in each poll item (your Answered2). But you also want an output row for the Answered1 value for each poll item, and here LINQ is less helpful. There are two ways you can do this, the quick and ugly way using Enumerable.Concat:
...
let v = ...
from answer in new [] { y.SelectedValue }.Concat(v.Items.Where(r => r.Selected)) // http://msdn.microsoft.com/en-us/library/bb302894.aspx
select new [] { z.Value, answer, "" }
Or the clearer and more general, but longer way, using yield to create an iterator method that gives you an item for all the answers:
from DataListItem item in PollDataList.Items
let z = ...
from answer in PollItemAnswers(item)
...
// outside the method containing the above
IEnumerable<object> PollItemAnswers(PollListItem item)
{
var y = ...; // As in let statements
var v = ...;
yield return y.Value; // return the first answer
foreach (var checkBox in v.Items)
if (checkBox.Selected)
yield return checkBox.Value; // return the other answers
}
And finally, if your final code don't have the items already separated (say, it was posted from a web form), you can use string.Split():
yield return y.Value;
foreach (var answer in value.Split(',')) // "a, b, c" -> "a", " b", " c"
yield return answer.Trim(); // " b" -> "b"
As a final note, watch out for if your answers could contain ,! In general, using something like JSON to safely move value collections around (say from a file or another machine) will save you a lot of grief.
I have an asp.net chckebox list:
<asp:EntityDataSource ID="GradeLevelEntityDataSource" runat="server"
ConnectionString="name=NewCourseRequestDataEntities"
DefaultContainerName="NewCourseRequestDataEntities" EnableFlattening="False"
EntitySetName="grade_levels" OrderBy="it.grade_level_index">
</asp:EntityDataSource>
<asp:CheckBoxList ID="GradeLevelCheckBoxList" runat="server" cssClass="horizontalcontrols"
DataSourceID="GradeLevelEntityDataSource"
DataTextField="grade_level_description" DataValueField="grade_level_id" AutoPostBack="True"
OnSelectedIndexChanged="CollegeInstitutionsListboxChange"
RepeatDirection="Horizontal" RepeatLayout="Flow">
</asp:CheckBoxList>
A user can return to the page, it gets the record ID, pulls the record data, and should check the appropriate checkboxes:
CheckBoxList grades = (CheckBoxList)FindControl("GradeLevelCheckBoxList");
foreach (request_grade_college r in CurrentRequest.request_grade_college)
{
ListItem grade = grades.Items.FindByValue(r.grade_level_id.ToString());
if (grade != null)
{
grade.Selected = true;
}
}
the portion of the code r.grade_level_id.ToString() does return the correct GUID, as type String. However, ListItem grade remain null, so none of the GradeLevelCheckboxList get checked.
What am I missing please?
I think that the data is not yet bound when you try to access it using Items.FindByValue(), try calling
grades.DataBind();
before the foreach loop.
Please make sure the listbox item's Value property has the correct value, if Item's Text and Value are different.
Also, Value Property and grade_level_id are exactly of same case and with trimmed spaces.
I'm binding an ASP.NET control to the result of a LINQ query. I'd like to HtmlEncode one of the properties of the contained objects before binding to the control, but I want to do it without altering the data because I do a DataContext.SubmitChanges() later on. How can this be done?
Code that won't work:
var ds = (from s in dc.SearchResults
orderby s.datetime descending
select s)
.Take(int.Parse(ConfigurationManager.AppSettings["RecentItemQty"]));
foreach (SearchResult sr in ds)
sr.Query = Server.HtmlEncode(sr.Query);
rSearches.DataSource = ds;
rSearches.DataBind();
Your could encode it when you do your binding...
<asp:YourDataBoundControl>
<ItemTemplate>
Query: <span><%# Server.HtmlEncode((string)Eval("Query")) %></span>
</ItemTemplate>
</asp:YourDataBoundControl>
Dummy me. I just need to HtmlEncode it within the OnItemDataBound() event.
Have two copies of the data:
from s in dc.SearchResults
orderby s.datetime descending
select new {
Original = s,
Encoded = Server.HtmlEncode(s.Query)
};
Or you could use HttpUtility.HtmlEncode('string');
Both are valid but the one above is available anywhere within an application easier than loading up HttpContext.Current.Server.HtmlEncode.