CheckBoxList with multiple values bound to a single flag enum - asp.net

I have a FormView (bound to an ObjectDataSource) that contains a CheckBoxList that I'd like to bind to a single property of the underlying object that is an Enum with the FlagsAttribute applied to it. Binding to the SelectedValue property always gives me just the FIRST selected value from the list as the property's value. Anyone know how to get around this without overriding the Inserting or Updating methods and manually getting the values of the checkbox list and stuffing it into the parameters of the datasource? Sample code below of what I'm trying to do...
<asp:FormView runat="server" ID="MyFormView" DataSourceID="MyDataSource">
<InsertItemTempate>
<asp:CheckBoxList runat="server" ID="MyCbl" SelectedValue='<%# Bind("MyProperty") %>'>
<asp:ListItem Text="Choice 1" Value="ChoiceOne"></asp:ListItem>
<asp:ListItem Text="Choice 2" Value="ChoiceTwo"></asp:ListItem>
</asp:CheckBoxList>
</InsertItemTemplate>
</asp:FormView>
<asp:ObjectDataSource runat="server" ID="MyDataSource" TypeName="MyClass" ...></asp:ObjectDataSource>
behind the scenes, my object is declared like this...
public class MyClass
{
public MyEnum MyProperty { get; set; }
}
[Flags()]
public Enum MyEnum
{
ChoiceOne = 1,
ChoiceTwo = 2
}

You will have to iterate through the Items collections and build up the enum values from there.
A search on Google for FlaggedEnumTypeConverter should also be helpful.

Related

Set SelectedValue of DropDownList inside DataGrid

I got a datagrid where a datasource #1 is bound to, e.g.
public class Class
{
public string Val { get; set; }
public string Val2 { get; set; }
}
List<Class> classes = new List<Class>();
dgr.DataSource = classes;
Inside this datagrid i got a listbox for each row with a datasource #2 bound to:
<Columns>
<asp:TemplateColumn HeaderText="Spaltenname">
<ItemTemplate>
<asp:ListBox runat="server" DataTextField="Text" DataValueField="Value" DataSource="<%#oParentTablesHandler.DataTableXYZ%>" />
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
This works, but I have problems setting the SelectedValue.
SelectedValue="<%# "" %>
will work but I need a selection depending on Val from datasource #1. How can I do that? I need to use Eval i guess, but
SelectedValue="<%# Eval("Val") %> did not work...
edit: I found out that I want to select an item by text and not by value, argh. Is there a way to do that?
Try like this..
<%# ((Class)Container.DataItem).Val %>
UPDATE:
well.there may be some value in 'Val' property that may not exist in your Datasource#2's corresponding column...
So for test purpose try following..
<asp:ListBox .. AppendDataBoundItems="true">
<Items>
<asp:ListItem Text="NA" Value="" />
</Items>
</asp:ListBox >

ASP.NET Binding integer to CheckBox's Checked field

I have a following ListView item template, in which I am trying to bind integer value to Checked property of CheckBox.
IsUploaded value contains only 0 and 1...
<asp:ListView ID="trustListView" runat="server">
<ItemTemplate>
<asp:CheckBox ID="isUploadedCheckBox" runat="server"
Checked='<%# Bind("IsUploaded") %>' />
</ItemTemplate>
</asp:ListView>
But ASP.NET complains that
Exception Details: System.InvalidCastException: Sepcified cast is not valid
Even though following code using DataBinder.Eval() works,
I need to have a 2-way binding, thus need to use Bind().
<asp:CheckBox ID="isUploadedCheckBox2" runat="server"
Checked='<%# Convert.ToBoolean(
DataBinder.Eval(Container.DataItem, "IsUploaded"))) %>' />
How can I convert 0's and 1's to boolean using Bind()?
[ANSWER]
I have extended auto-generated type through partial class by adding a new property mentioned in the answer by Justin
If you're willing to change the class, add a property on the class that's a boolean
public bool IsUploadedBoolean
{
get { return IsUploaded != 0; }
set { IsUploaded = value ? 1 : 0; }
}
If not, you may have success with a TypeConverter:
Create a custom TypeConverter which will handle 0 and 1 to boolean conversions
Stick the TypeConverterAttribute on the IsUploaded property to direct .NET to your custom typeconverter.
How about adding a property to your class which does the conversion?
public bool IsUploadedBool
{
get { return IsUploaded == 1; }
}
and then bind to this IsUploadedBool property instead of directly to the underlying INT.
Marc
Kind of a cheesy work around would be to use a drop down list with list items to give the same effect:
<asp:DropDownList ID="ddlBool" runat="server" SelectedValue= '<%# Bind("IsUploaded") %>'>
<asp:ListItem Text="True" Value="1" />
<asp:ListItem Text="False" Value="0" />
</asp:DropDownList>
For more information visit:
http://dhondiyals.wordpress.com/2010/05/03/binding-checkbox-with-integer-value-in-gridviewtrick/
How about (btw i am using a stored procedure)
Aspx page
<asp:CheckBox ID="social_facebook" runat="server" Checked='<%# Bind("True") %>' />Facebook
Code behind
cmd.Parameters.Add("#p_facebook", SqlDbType.Bit).Value = social_facebook.Checked;
Solution:
Hi, I'm also using Ajax rating inside a GridView and I ran into this problem. After looking through several forums, I tried this and it worked for me. I hope it helps you:
<%# Convert.ToInt32(Eval("EVALUATION")) %>
returns an integer, since you're using Checked which is an integer.

Using a FormView with LINQ

I am using a FormView control to edit a record fetched using a LinqDataSource. In essence, the markup for the FormView and the data source looks like this:
<asp:FormView ID="RuleInstancePropertiesFormView" runat="server" DataKeyNames="RuleInstanceId"
DataSourceID="RuleInstanceDataSource" DefaultMode="Edit" Visible="false"
CssClass="PropertiesTable">
<EditItemTemplate>
<asp:Label ID="RuleInstanceId" runat="server" Text='<%# Eval("RuleInstanceId") %>' />
<telerik:RadTextBox ID="RuleInstanceNameTextBox"
runat="server"
Text='<%# Bind("Rule.Name") %>' />
<telerik:RadTextBox ID="LimitIndexTextBox"
runat="server"
Text='<%# Bind("LimitIndex") %>' />
</EditItemTemplate>
</asp:FormView>
<asp:LinqDataSource ID="RuleInstanceDataSource" runat="server"
ContextTypeName="Questionnaire.QuestionnairesDataContext"
TableName="RuleInstances" EnableUpdate="true">
</asp:LinqDataSource>
The record I am editing has a foreign key reference to another table, namely the "Rule" table. In the FormView, I need to edit fields in this foreign key table (I have a binding to the Rule.Name field in the above code).
When I try to save my changes, the local field (LimitIndex) is saved correctly in the database, but the foreign field (Rule.Name) isn't. I'm a bit puzzled by this, as the FormView correctly fetches the current value of Rule.Name, but refuses to persist it back to the LINQ object.
I hope anyone can help, thanks :)
You're specifying which table to use as a datasource using the TableName property. This controls which table Linq2Sql will update and so is limiting the update to just the RulesInstances table.
Okay, I found an alternative (but not elegant) solution. I use an ObjectDataSource instead of a LinqDataSource. I have then defined an class
public class RuleInstanceProjection {
public RuleInstanceProjection(){}
// Bind properties from the LINQ object.
public RuleInstanceProjection(RuleInstance instance) { ... }
public int RuleInstanceId {get; set;}
public string Rule_Name {get;set;}
...
}
The object above takes a RuleInstance as constructor, and updates its own properties with all the values that I need in the FormView. I then configure the ObjectDataSource to use another custom class, RuleInstanceProjectionDS, as data source. This class handles updates and inserts of my custom RuleInstanceProjection class:
public class RuleInstanceProjectionDS
{
public RuleInstanceProjectionDS() { }
public RuleInstanceProjection GetRuleInstance(int ruleInstanceId)
{ /* Retrieve the RuleInstance, and instantiate
a RuleInstanceProjection object */ }
public void SaveInstanceProjection(InstanceProjection projection)
{ /* Map fields back to the LINQ objects and submit. */ }
}
I can therefore handle all mappings in these two classes. Now, I only have to decide if this is actually better than updating the GUI controls directly...
I must say it isn't the most elegant solution, and I hope there will be a better data binding framework in later versions of ASP.NET. The current one only seems to handle the most trivial cases :(.

ASP.NET: Bind a value to a custom user control inside a repeater

I have an ASP.NET control that binds data to a repeater. Inside that repeater, I have another custom user control. I want to pass a value to this second control based on the current binding item.
<asp:Repeater runat="server" ID="ProductList">
<ItemTemplate>
<p>Product ID: <%# Eval("ProductID") %></p>
<myControl:MyCoolUserControl runat="server" ProductID='<%# Eval("ProductID") %>' />
</ItemTemplate>
</asp:Repeater>
The repeater item template correctly prints out my Product ID with the Eval statement, but when I do the same thing to pass the Product ID to MyCoolUserControl, it doesn't work (if ProductID on MyCoolUserControl is a Nullable Int32 - I can debug it and it's always null).
Any ideas how I can do this?
I did a small test and I got it working if the ProductID is a string. After I changed it to and int in the usercontrol I got kind of the same problems.
I did a int.Parse in the datasource to the repeater and got it working again.
Check to see that the ProductId that you pass into the repeaters datasource is of type int.
Mytest app.
string[] values = new string[]{ "12", "13" };
MyRepeater.DataSource = from v in values
select new
{
ProdId = int.Parse(v)
};
MyRepeater.DataBind();
<asp:Repeater runat="server" ID="MyRepeater">
<ItemTemplate>
<My:control runat="server" ProductId='<%# Eval("ProdId") %>' />
</ItemTemplate>
</asp:Repeater>
and in the usercontrol:
public int? ProductId
{
set { MyLabel.Text = value.Value.ToString(); }
}

Binding Gridview to IList<BusinessObject> that contains an IList<BusinessObject>

I'm having trouble figuring out how to bind a custom IList to a gridview. The IList contains another custom IList. I need to bind a property from this IList to the gridview.
public class Seminar : BusinessObject
{
private string _description = String.Empty;
private List<User> _attendees;
public string Description {get {return _description;} set {_description = value;}}
public List<User> Attendees {get {return _attendees;} set {_attendees = value;}}
}
public class User : BusinessObject
{
private string _name = String.Empty;
public string Name { get { return _name; } set { _name = value; } }
}
Backend page.aspx.cs:
List<Seminar> seminarList = SeminarManager.Get(id);
gridSeminars.DataSource = seminarList;
gridSeminars.DataBind();
Frontend page.aspx:
<asp:GridView ID="gridSeminars" runat="server">
<Columns>
<asp:BoundField DataField="Id" />
<asp:BoundField DataField="Description" />
<asp:BoundField DataField="Name" />
</Columns>
</asp:GridView>
The problem is with populating the "Name" field in the gridview. All suggestions are welcome.
Have you tried,
Attendees.Name
Edit:
Attendees is an IEnumerable itself. The above suggestion only works with Attendee.Name
If you wan´t to display all the attendees you need to make a templatefield and maybe use a repeater or something...something like:
<asp:TemplateField>
<ItemTemplate>
<asp:Repeater runat="server" DataSource='<%# Eval("Attendees") %>'>
<ItemTemplate>
<tr>
<td>
Name
</td>
<td>
<%# Eval("Name")%>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:TemplateField>
Johan's answer is a good one, specifically the part about how you are trying to bind a collection to a column that is expecting something that can be converted to a string.
Another option would be to put a TemplateField that contains the bindable control (Repeater, another GridView, etc.) you choose to use and binding the DataSource property to the Attendees property of your business object.
Also, I don't if you're married to the idea of using a GridView, but in cases like these where you need more control of the layout, I would suggest the new ListView (.NET 3.5) control, or lately I've just been using nested repeaters so I can have more refined control of the layout I am trying to generate.
Hope this helps.
I'm assuming you want to flatten the hierarchy and display one row for every user. If you have access to Linq, you can use this:
List<Seminar> seminarList = SeminarManager.Get(id);
gridSeminars.DataSource = from seminar in seminarList // loop through all of the seminars in the list
from user in seminar.Attendees // loop through all of the users in the current seminar
select new // create a new, flattened object to bind to.
{
seminar.Id,
seminar.Description,
user.Name
};
gridSeminars.DataBind();
http://weblogs.asp.net/zeeshanhirani/archive/2008/03/26/select-many-operator-part-1.aspx

Resources