I'm having headache with Time values and multiple time zones.
I'm storing new DateTime values in UTC time, but I face problem when I try to modify them using LinqDataSource and GridView.
I can easily show correct time in
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# TimeManager.ToLocalTime((DateTime)Eval("OrderDate")) %>' />
</ItemTemplate>
Currently this will add 1 hour to UTC time stored in DB.
However, binding back to source is not easy. Bind("OrderDate") cannot be modified like TimeManager.ToGlobalTime((DateTime)Bind("OrderDate")).
I was thinking of using OnUpdating event of LinqDataSource to update value to global time, but what if user modified other fields and not date field? Every time he updates record time value would be smaller for one hour.
Comparing old and new values also is not great because user can modify date portion of datetime and not time, which is influenced by time zones?
If I had way to show local time in gridview's all states then I could easily use OnUpdating of LinqDataSource.
Please share your thoughts...
Have you considered making the change to your model? Let's assume that the name of the object you are binding to is CustomerOrder. You could add the following class to your project (in the same namespace as your Linq objects):
public partial class CustomerOrder
{
public DateTime LocalOrderDate
{
get { return TimeManager.ToLocalTime(OrderDate); }
set { OrderDate = TimeManager.ToUTCTime(value); }
}
}
Now instead of binding to OrderDate, bind to LocalOrderDate. This will automatically make the UTC / Local Time conversion to the OrderDate.
(Note: I'm assuming you have TimeManager.ToLocalTime() and TimeManager. ToUTCTime() properly defined)
The way I've handled this sort of thing in the past is to use Eval in the EditItemTemplate as well. Let the user edit the item in local time. Then add OnItemUpdating handler for the gridview and add extract the value of the associated text box, convert it to global time, and add that to the new values dictionary. Bind the original value in (in global time) to a hidden field in the same template, which will populate the old values dictionary with the correct old time. You'll want to do the same thing on insertion in OnItemInserting although you obviously don't need the old value (since there isn't one).
EDIT: Usually I do my updates on a DetailsView not a GridView, thus the ItemUpdating/Inserting instead of RowUpdating/Inserting. Sample code below -- this example uses a pair of dropdown lists that allows the user to specific a location (choose a building and a location in the building, but it actually only maps the location in the database). On the back end it assigns initial values to the dropdowns in OnPreRender (not shown) and extracts the LocationID database field value from the location dropdown on ItemUpdating/Inserting (updating shown). The DetailsView is wrapped in an UpdatePanel and the population of the Location dropdown is done when the building dropdown selection changes. Note that since I'm updating the item (causing an update statement anyway) I don't care if the LocationID field gets overwritten on the update with the same value so I don't bother to keep the old value on the page.
<asp:TemplateField HeaderText="Location:" SortExpression="LocationId">
<EditItemTemplate>
<asp:DropDownList runat="server" ID="buildingDropDownList"
DataSourceID="buildingDataSource"
DataTextField="name"
DataValueField="abbreviation"
OnSelectedIndexChanged=
"buildingDropDownList_SelectedIndexChanged"
AutoPostBack="true" />
<asp:DropDownList runat="server" ID="locationDropDownList"
DataSourceID="locationsDataSource"
DataTextField="Name"
DataValueField="ID">
</asp:DropDownList>
</EditItemTemplate>
<InsertItemTemplate>
<asp:DropDownList runat="server" ID="buildingDropDownList"
DataSourceID="buildingDataSource"
DataTextField="name"
DataValueField="abbreviation"
OnSelectedIndexChanged=
"buildingDropDownList_SelectedIndexChanged"
AutoPostBack="true"
AppendDataBoundItems="true">
<asp:ListItem Text="Select Building" Value="" />
</asp:DropDownList>
<asp:DropDownList runat="server" ID="locationDropDownList"
DataSourceID="locationsDataSource"
DataTextField="Name"
DataValueField="ID"
AppendDataBoundItems="true">
<asp:ListItem Text="Not installed" Value="" />
</asp:DropDownList>
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID="locationLabel" runat="server"\
Text='<%# Eval("LocationID") == null
? ""
: Eval("Location.Name") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
Codebehind:
void editPrinterDetailsView_ItemUpdating( object sender,
DetailsViewUpdateEventArgs e )
{
// Use a helper method to find the dropdown inside the details view
// and get the selected value.
string locationID = ControlHelper
.GetDropDownValue( editPrinterDetailsView,
"locationDropDownList" );
if (locationID == string.Empty)
{
locationID = null;
}
if (e.NewValues.Contains( "LocationID" ))
{
e.NewValues["LocationID"] = locationID;
}
else
{
e.NewValues.Add( "LocationID", locationID );
}
e.OldValues["LocationID"] = -1;
}
Related
I'm retrofitting an older web forms site with Model Binding using asp.net 4.5.
In a DetailsView I have a drop down list that allows selection of a particular 'client' and another that allows selection of a particular 'project' that belongs to that client. So the drop down for project has to be filtered on the client number and if the user changes the client selection, I want to filter the project list by client number.
I couldn't figure out how to get the SelectedIndexChanged method on the client ddl to fire the Select method for the Project, so I concluded the only way to do it was to filter the project ddl by client number in all cases. I am getting an error message when the client selection is made:
NullReferenceException was Unhandled by User Code
which point in my aspx directly to the ddl for Projects.
This is an abbreviated version of the details view, you can see both the clients ddl and the projects ddl (I am operating in Edit mode):
<asp:DetailsView ID="AdministratorDetailsView" runat="server" AutoGenerateRows="False"
DataKeyNames="AdministratorNumber" ItemType="BusinessLogic.Administrator"
Width="99%"
SelectMethod="AdministratorDetailsView_GetItem"
UpdateMethod="AdministratorDetailsView_UpdateItem"
DeleteMethod="AdministratorDetailsView_DeleteItem"
FieldHeaderStyle-Width="30%" EditRowStyle-Width="99%"
InsertRowStyle-Width="70%" RowStyle-Width="99%" CssClass="admin"
AutoGenerateDeleteButton="true" AutoGenerateEditButton="true" >
<Fields>
<asp:TemplateField HeaderText="AdministratorCode" SortExpression="AdministratorCode">
<EditItemTemplate>
<asp:Label ID="AdministratorCode" Text="<%# Item.AdministratorCode%>" runat="server" />
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="AdministratorCode" Text="<%# Item.AdministratorCode%>" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ClientNumber" SortExpression="ClientNumber">
<EditItemTemplate>
<asp:DropDownList ID="ddClients" runat="server"
AutoPostBack="true"
DataTextField="ClientName" DataValueField="ClientNumber"
ItemType="BusinessLogic.Client"
SelectMethod="ddClients_GetList"
SelectedValue="<%# Item.ClientNumber%>"
OnSelectedIndexChanged="AdministratorDetailsView_ddlClients_SelectedIndexChanged"/>
</EditItemTemplate>
<ItemTemplate>
<asp:DropDownList ID="ddClients" runat="server" Enabled="false"
DataTextField="ClientName" DataValueField="ClientNumber"
ItemType="BusinessLogic.Client"
SelectMethod="ddClients_GetList"
SelectedValue="<%# Item.ClientNumber%>"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Projects" >
<EditItemTemplate>
<asp:DropDownList ID="ddProjects" runat="server" AutoPostBack="true"
DataTextField="ProjectName" DataValueField="ProjectNumber"
ItemType="BusinessLogic.Project"
SelectMethod="ddProjects_GetList"
SelectedValue="<%# Item.ProjectNumber%>" />
</EditItemTemplate>
<ItemTemplate>
<asp:DropDownList ID="ddProjects" runat="server" Enabled="false"
DataTextField="ProjectName" DataValueField="ProjectNumber"
ItemType="BusinessLogic.Project"
SelectMethod="ddProjects_GetList"
SelectedValue="<%# Item.ProjectNumber%>"/>
</ItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
There are two SelectMethods, one for each drop down list, and a selectedindexchaneged method for clients:
Public Function ddClients_GetList() As List(Of BusinessLogic.Client)
Dim special As New List(Of Client)
special = CurrentClient.ClientList() 'add whole list
Dim NullClient As New Client()
NullClient.Load(0)
NullClient.ClientName = "<-Not Selected-->"
special.Add(NullClient) 'Had to have a client with 0 in the list since most admins don't have anything but 0 inthis field
Return special
End Function
Public Function ddProjects_GetList(<Control("ddClients")> ByVal ClientNumber As Integer) As List(Of BusinessLogic.Project)
Dim special As New List(Of Project)
If ClientNumber = 0 Then
special = CurrentProject.ProjectList() 'add whole list, refine it if Clients Drop Down selected
Else
special = CurrentProject.ProjectList(ClientNumber) 'add whole list, refine it if Clients Drop Down selected
End If
Dim NullProject As New Project()
NullProject.Load(0)
NullProject.ProjectName = "<-Not Selected-->"
special.Add(NullProject) 'Had to have a Project with 0 in the list since most admins don't have anything but 0 inthis field
Return special
End Function
Protected Sub AdministratorDetailsView_ddlClients_SelectedIndexChanged(sender As Object, e As EventArgs)
Dim ddlProj As DropDownList
ddlProj = AdministratorDetailsView.FindControl("ddProjects")
ddlProj.ItemType = "BusinessLogic.Project"
ddlProj.DataBind()
End Sub
All is well until the user selects a different client which triggers the SelectIndexChanged event and then we get to the DataBind(), where we get the null exception (ddlProj is found).
Need some ideas on how to refresh the projects list based on the new client selection.
How do I force ddProjects to run its SelectMethod again, to avoid the null reference and reload the control?
Turns out this issue is not unique to ModelBinding, but is a General WebForms Issue.
You cannot have cascading dropdowns within another data control where they depend on each other unless you add a bit of code.
In my case, I was trying to bind both dropdowns to the underlying detailsview, and at the same time setting the selected values. Doesn't work because of timing. It seems right until you try to change the selection on the parent dropdown, and then you get null exception on the second because it is not yet loaded. It's all timing. If you try to work around it with saved values, it gets too messy.
My solution is, Bind another item to the underlying details view (you can make it hidden if you wish). Then add some code to keep it in sync with the actual value. DO NOT Bind SelectedValue on the secondary drop down , this is what causes the problem. Manage Selected Value in code using the added field.
<asp:DetailsView ID="AdministratorDetailsView" runat="server" AutoGenerateRows="False"
DataKeyNames="AdministratorNumber" ItemType="BusinessLogic.Administrator"
Width="99%" SelectMethod="AdministratorDetailsView_GetItem" UpdateMethod="AdministratorDetailsView_UpdateItem" DeleteMethod="AdministratorDetailsView_DeleteItem"
FieldHeaderStyle-Width="30%" EditRowStyle-Width="99%" InsertRowStyle-Width="70%" RowStyle-Width="99%" CssClass="admin" AutoGenerateDeleteButton="true" AutoGenerateEditButton="true"
>
<Fields>
<asp:TemplateField HeaderText="Client Name" SortExpression="ClientName">
<EditItemTemplate><asp:DropDownList ID="ddClients" runat="server" AutoPostBack="true" DataTextField="ClientName" DataValueField="ClientNumber" ItemType="BusinessLogic.Client" SelectMethod="ddClients_GetList" SelectedValue="<%# Item.ClientNumber%>" OnDataBound="ddClients_DataBound" OnSelectedIndexChanged="AdministratorDetailsView_ddlClients_SelectedIndexChanged" /> </EditItemTemplate>
<ItemTemplate><asp:DropDownList ID="ddClients" runat="server" Enabled="false" DataTextField="ClientName" DataValueField="ClientNumber" ItemType="BusinessLogic.Client" SelectMethod="ddClients_GetList" SelectedValue="<%# Item.ClientNumber%>"/></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText ="Project Number" >
<EditItemTemplate><asp:Label ID="ProjectNumberLabel" runat="server" Text="<%# BindItem.ProjectNumber%>"></asp:Label></EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Project Name" SortExpression="ProjectNumber">
<EditItemTemplate><asp:DropDownList ID="ddProjects" runat="server" AutoPostBack="true" DataTextField="ProjectName" DataValueField="ProjectNumber" ItemType="BusinessLogic.Project" SelectMethod="ddProjects_GetList" OnDataBound="ddProjects_DataBound" OnSelectedIndexChanged="ddProjects_SelectedIndexChanged" />
</EditItemTemplate>
<ItemTemplate><asp:DropDownList ID="ddProjects" runat="server" Enabled="false" DataTextField="ProjectName" DataValueField="ProjectNumber" ItemType="BusinessLogic.Project" SelectMethod="ddProjects_GetList" SelectedValue="<%# Item.ProjectNumber%>" />
</ItemTemplate>
</asp:TemplateField>
</asp:DetailsView>
And in the code behind, not how we set and get the value of the bound projectnumber:
Protected Sub AdministratorDetailsView_ddlClients_SelectedIndexChanged(sender As Object, e As EventArgs)
''If this selection changes we need to change some flags and perhaps theProject ddl
''This causes null exception for Project ddl, can't figure out how to get it to reload. Tried DataBind(), same effect as having a ValueProvider in the parameters to the Select
Dim ProjectNumberLabel As Label = AdministratorDetailsView.FindControl("ProjectNumberLabel")
ProjectNumberLabel.Text = "0" 'Synchronize to no selection
Dim ddProjects As New DropDownList
ddProjects = AdministratorDetailsView.FindControl("ddProjects") 'Have to use Find Control because ddl is buried in DetailsView
ddProjects.SelectedValue = 0 'Cause it to read Select an Item
ddProjects.DataBind() 'Rebinding it causes the SelectMethod to run.
End Sub
Protected Sub ddProjects_DataBound(sender As Object, e As EventArgs)
'Because of the problem with cascading references, we had to remove the SelectValue declaration from ddProjects.
'So we must make sure that once theddProjects is databound, it points to the selected value from the data
Dim ddlProjects As DropDownList
ddlProjects = AdministratorDetailsView.FindControl("ddProjects")
Dim ProjectNumberLabel As Label = AdministratorDetailsView.FindControl("ProjectNumberLabel")
ddlProjects.SelectedValue = CInt(ProjectNumberLabel.Text)
End Sub
Hope someone else sees this as useful. I couldn't find it anywhere.
Great posting, as I faced a similar conundrum and it made me think. I have done this before outside of the model-binding approach, and the solution is essentially the same, as described. I used a ListView, and added the method:
OnItemDataBound="lvWhatever_ItemDataBound"
to fire an event from which to go and get the relevant ID from another bound control in the list view data item:
if (e.Item.ItemType == ListViewItemType.DataItem)
{
// get the ID from from another control in this item record: lblItemID
ListViewDataItem lvdi = (ListViewDataItem)e.Item;
if (lvdi != null)
{
Label iID = (Label)lvdi.FindControl("lblItemID");
if (iID != null)
where lblItemID.Text contains the relevant ID. Then from that I can query to get the relevant list, and manually bind it to the DDL. Brilliant - thanks very much.
Hi I have following grid view
<asp:GridView ID="grdSettings" runat="server" Height="400px" Width="100%"
AutoGenerateColumns="false" >
<Columns>
<asp:TemplateField HeaderText="XYZ" BoundFieldName="XYZTypeName">
<ItemTemplate>
<asp:Label ID="lblCustomerName" runat="server" Text='<%# Bind("CustomerName") %>'>
</asp:Label>
<asp:Label ID="lblCostumerId" runat="server" Text='<%#Bind("CustomerId") %>'></asp:Label>
</asp:TemplateField>
</Columns>
</asp:GridView>
Which is bound by List of Customer ,class is as follows
Class Customer
{
public string CustomerName { get; set; }
public int CustomerId { get; set; }
}
Now on a method named GetGridStuff() , i need to iterate in every column and get the type that was bound to controls in template field. For example in case of the first control in the template field
<asp:Label ID="lblCustomerName" runat="server" Text='<%# Bind("CustomerName") %>' >
</asp:Label>
I need to know what type of property data it contains , in this case its CustomerName. I need to get this dynamically at run time as to write code in part of program which is not aware if this grid structure. I have the grid object with me and i can access all properties.
Let me try this, being away from coding for more than 5 years now and if I understand the problem correctly as you may want to handle it through server side code.
Look for an event called ItemBound (or similar forgive me for my memory), this gives you values of all the items in current row (Properties). You also need to declare temp control types (label,textbox etc) and assign corresponding value to these controls using e.FindControl with appropriate type casting, e.g. Label l = (Label)e.Findcontrol("Name")
downside of the approach you should avoid too much of process as it is going to execute on every row creating of the grid.
Let me know if you still want a precise code to handle the problem but otherwise this description should at least help you to look for Row Level Event to crack the prob and also encourage you to stick to tech forums :)
I'm using LINQ to SQL and want to be able to select a parent or no parent. Let's say I have a People table with PersonId, Name and ParentId columns. In ASP I want to enter the name, select a parent and click 'Add' to create a new Person record, but I also want to be able to leave the ParentId null. Don't ask why, this is just a simplified explanation for what I want to do.
<asp:LinqDataSource ID="LinqPeople" runat="server"
ContextTypeName="MyDataContext" EntityTypeName=""
Select="new (PersonId, Name)" TableName="People"/>
<asp:TextBox ID="textName" runat="server" />
<asp:DropDownList runat="server" ID="dropParent"
DataSourceID="LinqPeople" DataTextField="Name" DataValueField="PersonId" />
<asp:Button ID="buttonAddPerson" runat="server" Text="Add" />
Is there any way to display 'None' in the list box with a value of null? I have thought of a few options, which is best or are there any others?
Create a stored procedure for the SQL "SELECT PersonId, Name FROM People UNION SELECT Null, 'NONE'"
Add a CheckBox for "NO PARENT"
Put a ListItem in the markup for the DropDownList
Add the item on the DataBound event handler
I found a better way, adding a ListItem in the markup:
<asp:LinqDataSource ID="LinqPeople" runat="server"
ContextTypeName="MyDataContext" EntityTypeName=""
Select="new (PersonId, Name)" TableName="People"/>
<asp:TextBox ID="textName" runat="server" />
<asp:DropDownList runat="server" ID="dropParent"
DataSourceID="LinqPeople" DataTextField="Name" DataValueField="PersonId">
<asp:ListItem Value="">(none)</asp:ListItem>
</asp:DropDownList>
<asp:Button ID="buttonAddPerson" runat="server" Text="Add" />
I cannot find any way to return the actual value 'NULL' in SelectedValue however, but I can handle that I guess. I think the ListItem way is the best because it is defined in the markup and doesn't require any code...
Don't think you can set the value of NULL since it's a string type.
I don't like the check for NULL, typically, I would use something that doesn't make sense, like -1 or something and check for that. You could also assume that your selected index is 0, however, that could cause problems somewhere else in code if you don't follow throughout the app.
So in this gridview, there is a column for status and I want to have a drop down list with Pass, Pending, Fail appear when the edit button is clicked. These values are already in a table, so I need to somehow bind from this table to each ddl for every row.
Here is the column from the gridview. As you can see, I would like to just have a label showing when not in edit mode, and a ddl when the edit button is pressed
<asp:TemplateField HeaderText="During Production Status" SortExpression="DuringProductionStatus">
<EditItemTemplate>
<asp:DropDownList ID="ddlStatus" runat="server" datavaluefield="Name"
datatextfield="Name" DataSource="*What goes here?*"> />
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblStatus" runat="server"
Text='I don't understand how to get this from the ddl' />
</ItemTemplate>
</asp:TemplateField>
For clarity's sake, my table is named Status, and the database is named DirectImport
There's a few steps to go through here - none of them are particularly difficult, but they can be a bit fiddly (IMHO). The good news is once you've got this working once, it gets easier to do it again!
I'm assuming you've got a <asp:*DataSource> control on your page - my preference is for an ObjectDataSource but I don't think it matters, I think a SqlDataSource works equally well. I've never tried doing this with GridView.DataSource = MyDataSet in code-behind, so I don't know whether that would work or not, but my assumption is that it wouldn't as you wouldn't get the proper two-way binding that you want. This data source feeds your grid with your main data. The key point here is that your database query must return both the Status text field and the Status id.
So your gridview will now look something like:
<asp:objectdatasource runat="server" id="MainDataSource" ... />
<asp:gridview runat="server" id="MyGridView" DataSourceID="MainDataSource">
<Columns>
<asp:TemplateField HeaderText="During Production Status" SortExpression="DuringProductionStatus">
<ItemTemplate>
<asp:Label ID="lblStatus" runat="server"
Text="<%# Bind('Status') %>" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:gridview>
The Text="<%# Bind('Status') %>" is the bit you're missing to get the status text into the grid.
Now add a second data source into your markup that reads in the set of values from the Status table.
<asp:objectdatasource runat="server" id="StatusObjectDataSource" ... />
And add the EditItemTemplate into the GridView, which is bound to the Status DataSource.
<EditItemTemplate>
<asp:DropDownList ID="ddlStatus" runat="server" datavaluefield="StatusID"
datatextfield="Status" DataSourceID="StatusObjectDataSource"
SelectedValue="<%# Bind('StatusId') %>" />
</EditItemTemplate>
The SelectedValue="<%# Bind('StatusId') %>" is what connects up the two datasets so that when you flip a row into Edit mode, the dropdownlist has the correct item already selected, and when you then save it you've got the Status ID to put into your database.
And you're done.
I have used the RowDataBound event. Here is a small code snippet. HTH
you would have an ItemTemplate in your aspx/ascx
<asp:TemplateField HeaderText="Column Headings">
<ItemTemplate>
<asp:DropDownList ID="ddlName" runat="server" Width="150"></asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
and in your code behind, you will have
protected void grdDataMap_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddl = (DropDownList)e.Row.FindControl("ddlName");
ddl.DataSource = someList;//the source of your dropdown
ddl.DataBind();
}
}
so when you bind your grid with grdDataMap.Databind (assuming your grid id is grdDataMap), row databound event will be called for each row (including header/footer, and thats the reason you check RowType)
so you can probably decide what controls/columns to hide/show/bind inside this row databound event
In the winforms world I pull my objects from the DB into a List(Of Whatever) and use the list as the datasource.
This also lets me add extra "convenience" fields in the object so that I can populate it with stuff from other tables.
I don't know asp.net at all so if you can do something similar, it might help.
A really quick solution is to create a custom web control for the status dropdown. The control will always contain the same data. When it renders you populate the datasource. When it gets added to the gridview, the data will be in the drop down. Hope that helps!
I have a Repeater control on ASPX-page defined like this:
<asp:Repeater ID="answerVariantRepeater" runat="server"
onitemdatabound="answerVariantRepeater_ItemDataBound">
<ItemTemplate>
<asp:RadioButton ID="answerVariantRadioButton" runat="server"
GroupName="answerVariants"
Text='<%# DataBinder.Eval(Container.DataItem, "Text")%>'"/>
</ItemTemplate>
</asp:Repeater>
To allow select only one radio button in time I have used a trick form this article.
But now when form is submitted I want to determine which radio button is checked.
I could do this:
RadioButton checkedButton = null;
foreach (RepeaterItem item in answerVariantRepeater.Items)
{
RadioButton control=(RadioButton)item.FindControl("answerVariantRadioButton");
if (control.Checked)
{
checkedButton = control;
break;
}
}
but hope it could be done somehow simplier (maybe via LINQ to objects).
You could always use Request.Form to get the submitted radio button:
var value = Request.Form["answerVariants"];
I think the submitted value defaults to the id of the <asp:RadioButton /> that was selected, but you can always add a value attribute - even though it's not officially an <asp:RadioButton /> property - and this will then be the submitted value:
<asp:RadioButton ID="answerVariantRadioButton" runat="server"
GroupName="answerVariants"
Text='<%# DataBinder.Eval(Container.DataItem, "Text")%>'"
value='<%# DataBinder.Eval(Container.DataItem, "SomethingToUseAsTheValue")%>' />
Since You are using javascript already to handle the radio button click event on the client, you could update a hidden field with the selected value at the same time.
Your server code would then just access the selected value from the hidden field.
I'm pretty sure that the only thing you could use LINQ to Objects for here would be to take the conditions from within the foreach loop and move them to a where clause.
RadioButton checked =
(from item in answerVariantRepeater.Items
let radioButton = (RadioButton)item.FindControl("answerVariantRadioButton")
where radioButton.Checked
select radioButton).FirstOrDefault();