I want to scaffold a basic insert form which has dropdowns for the foreign keys.
I cant seem to figure out how to do this. When creating the metadata all the MetaColumns are of type MetaColumns, and none of type MetaForeignKeyColumns - which means that it renders textboxes for all properties - and no dropdown lists.
UIHints seem ineffective. I am using entity framework code first. How do I go about making those textboxes into dropdowns? In fact, I think the MetaData property is not being created ( I am probably missing something here ).
AddPermission.aspx (form only)
<asp:FormView runat="server" ID="AddPermissionForm"
ItemType="Common.Models.tag_permission"
InsertMethod="AddPermissionsForm_InsertItem" DefaultMode="Insert"
RenderOuterTable="false" OnItemInserted="AddPermissionForm_ItemInserted">
<InsertItemTemplate>
<fieldset>
<ol>
<asp:DynamicEntity runat="server" Mode="Insert" EnableViewState="true" ></asp:DynamicEntity>
</ol>
<asp:Button class="btn btn-primary" runat="server" Text="Insert" CommandName="Insert" />
<asp:Button class="btn btn-default" runat="server" Text="Cancel" CausesValidation="false" OnClick="CancelButton_Click" />
</fieldset>
</InsertItemTemplate>
tag_permission.cs ( part of code first model )
public partial class tag_permission
{
[ScaffoldColumn(false)]
public short tp_tag_permission_id { get; set; }
//foreign key one
public string tp_security_group_id { get; set; }
//foreign key two
public short tp_tag_id { get; set; }
[Display(Name = "View")]
public Nullable<bool> tp_vis { get; set; }
}
I might have to use a DynamicDataManager or something, but I'm not sure where to find how or if it should be used on this page alongside the formview.
I've also attached screenshots comparing the rendering of Default_Insert.aspx.cs in my web app, and a basic DynamicData website - almost out of the box from template. In the below pictures, the MetaTable Table property is being inspected in DynamicData/Default_Insert.ascx.cs.
The later image has an incomplete MetaTable property. It has null values for the DataContextType and DataContextPropertyName, and ForeignKeyColumnNames. I'd really like to set the MetaTable on the FormView properly
For reference: The code from the images below is
public partial class Default_InsertEntityTemplate : System.Web.DynamicData.EntityTemplateUserControl {
private MetaColumn currentColumn;
protected override void OnLoad(EventArgs e) {
foreach (MetaColumn column in Table.GetScaffoldColumns(Mode, ContainerType)) {
currentColumn = column;
Control item = new DefaultEntityTemplate._NamingContainer();
EntityTemplate1.ItemTemplate.InstantiateIn(item);
EntityTemplate1.Controls.Add(item);
}
}
...
DynamicData Web Site
My Web Application
Theres a few parts to this one:
On startup, I registered the dynamic data provider in global.asax
Global.asax.cs / other
App.DefaultModel.RegisterContext(
new Microsoft.AspNet.DynamicData.ModelProviders.EFDataModelProvider(() => new MyDbContext()),
new ContextConfiguration { ScaffoldAllTables = true });
App.cs ( a static class I use to store permanent references )
public static class App
...
private static MetaModel s_defaultModel = new MetaModel();
public static MetaModel DefaultModel
{get{ return s_defaultModel; }}
}
then on the page where I want to get the meta data I can do this
ModelMetaTable meta = App.DefaultModel.GetTable( nameof(db.MyAwsomeName) );
and then set the metadata
MyAwesomeForm.SetMetaTable(table);
and then the form will render will all foreign keys / navigation properties as they would in a dynamic data website.
All the properties of the ModelMetadata are then set and populated as you would expect - eg with the DataContext and ForeignKeyName are no longer null
Related
I have this Web Control call uc_Register.asxc
Inside this web control got a Text Box i.e txtName
I add this Web Control into my web page call register.aspx
<%# Register Src="~/controls/uc_Register.ascx" TagPrefix="ecommmbs" TagName="uc_Register" %>
<hr />
<ecommmbs:uc_SummaryCart runat="server" ID="uc_SummaryCart" />
<hr />
i want to get the value from txtName.txt from uc_Register.asxc at register.aspx.
how to make this happen?
Try this in Register.aspx
TextBox txtbox = (TextBox)uc_Register.FindControl("txtName");
but keep in mind Page_Load() of aspx page is called first than Page_Load()of .ascx is called.
Here is an example:
Declare On User Control (PrevTransList2.ascx.cs)
public string TransHxPage
{
get
{
return name;
}
set
{
name = value;
}
}
On Class file
public interface IUserControlTransHx
{
string TransHxPage { get; set; }
}
txtSomthing.Text = TransHxPage;
Now On Web page SET its values
PrevTransList2.TransHxPage = "POSP";
On my current project I need to add a functionality that allows the user to view a thumbnail of their uploaded PDF. I've found a handy component that achieves this (the basic version is free, but it's enough for my current needs). Anyways, the control is pretty outdated (2010), therefore there doesn't seem to be MVC support. On the demos they depict usage of the control as such:
The View's Markup:
<form method="post" runat="server" enctype="multipart/form-data">
<asp:Panel ID="thumbnailsPanel" runat="server" />
</form>
The thumbnail control is instantiated via code, the byte array which represents the thumbnail is passed to the control and the control is added to thumbnailsPanel
<script runat="server">
protected void DisplayThumbs_Click( object sender, System.EventArgs e )
{
Thumbnail thumbnail = new Thumbnail();
thumbnail.SessionKey = sessionID;
thumbnail.Index = i;
thumbnailsPanel.Controls.Add( thumbnail );
}
</script>
Given that I can't declare a Thumbnail control in my razor view, how would I used this control in MVC? I've spent a few hours trying to make this control MVC friendly to no avail, the best I've come up with is to include a .ASPX view (not.cshtml) in my project and render the Thumbnail control on that view. Obviously this is not desirable.
So how would you go about using a ASPX server controls in MVC? Is the idea a bad one altogether and should not be practised?
I worked around it in a project of mine by reimplementing the control as a HtmlHelper. Assuming the control isn't too complicated then it should work for you too. Do this:
Dump the Control's source using Reflector
Massage the source so it actually compiles (as source from Reflector doesn't usually compile straight away)
Identify what state the control has. Convert the state from member properties into members of its own new ViewModel class.
Find the Render method and convert it to a HtmlHelper that uses ViewContext.Writer
For example:
public class FooControl : Control {
public String Message { get; set; }
public override void Render(HtmlTextWriter wtr) {
wtr.WriteLine("<p>");
wtr.WriteLine( message );
wtr.WriteLine("</p>");
}
}
Becomes this:
public class FooViewModel {
public String Message { get; set; }
}
// This method should exist in a static Extensions class for HtmlHelper
public static void Foo(this HtmlHelper html, FooViewModel model) {
HtmlTextWriter wtr = html.ViewContext.Writer;
wtr.WriteLine("<p>");
wtr.WriteLine( model.Message );
wtr.WriteLine("</p>");
}
I would like to add a attribute to a custom control to extend it's feature.
<ns:PasswordChange
runat="server"
ID="pwch"
UserId='<%# ResidentId %>' />
In the code ..
[ToolboxData("<{0}:PasswordChange runat=server />")]
public class PasswordChange : WebControl
{
public string UserId { get; set; }
public override void RenderControl(HtmlTextWriter writer)
{
writer.Write("<script type=\"text/javascript\">");
writer.Write(script.Replace("{0}",***ajaxCall***));
writer.Write("</script>");
}
......
The parameter ajaxCall above contain the result of the evaulated if (string.IsNullOrEmpty(this.UserId)). That evaluation simply add one ajax-URL if there are a UserId, if not, another url.
The problem is that UserId isn't loaded at the time of RenderControl. It's not so surprising because this is the code that tells the user that UserId is an available attribute at all.
I would like some help/advice how I solve this kind of problem. The attribute is of course there for behavior of the control. I'm not superfamiliar with the execution-model of those controls.
I would try adding a LiteralControl during rendering, and populate it on PreLoad based on the value of UserID.
I'm setting up a web application with multiple forms. Each form is defined within an asp:FormView with the DataSource set to an ObjectDataSource. Each form contains it's own set of fields and always contains one or more blocks of fields, which are the same for multiple forms.
Because this blocks are the same, I decided to define them in a custom usercontrol. The questions that came up with this:
How can I use the same datasource
for the input fields in the
usercontrol as in the 'higher'
asp:FormView?
Is it possible to use DataBinding.Bind() for the input fields in the usercontrol, with this same datasource?
Thanks in advance for replies.
After a long search, I found a similar problem on this website: http://weblogs.asp.net/anasghanem/archive/2009/03/31/sharing-formview-edit-and-insert-templates-and-avoid-duplicate-markup.aspx.
In short the solution hierarchy:
<asp:FormView ID="FormView1" runat="server" DefaultMode="Edit" DataSourceID="ObjectDataSource1">
<uc1:TestControl ID="TestControl1" runat="server" PhoneNumber='<%# Bind("PhoneNumber") %>' />
And the codebehind for the usercontrol:
[Bindable(true)]
public partial class TestControl : System.Web.UI.UserControl
{
[Bindable(true), DefaultValue("")]
public string PhoneNumber
{
get
{
return this.PhoneTextBox.Text;
}
set
{
this.PhoneTextBox.Text = value;
}
}
}
I am trying to add a template to a simplified composite control containing a Label and a TextBox. I want my mark up to look something like this:
<test:FormItem ID="fi" runat="server" Title="MyTitle" Text="My Text!">
<TestTemplate>
<i>
<%# Container.Title) %></i>
<br />
<%# Container.Text %>
</TestTemplate>
</test:FormItem>
I have a templateContainer class that has properties for the TextBox and Label.
public class TemplateContainer : WebControl, INamingContainer
{
public TextBox Text { get { return m_item.Text; } }
public Label Title { get { return m_item.Title; } }
private FormItem m_item;
public TemplateContainer(FormItem item)
{
m_item = item;
}
}
In the main FormItem class I have a CreateControlHierarchy() method that is being called from CreateChildControls():
protected virtual void CreateControlHierarchy()
{
m_itemTemplateContainer = new TemplateContainer(this);
TestTemplate.InstantiateIn(m_itemTemplateContainer);
Controls.Add(m_itemTemplateContainer);
}
What I WANT is for the Template to render the actual control. Instead, it's calling ToString() on the control and displaying System.Web.UI.WebControls.Label and System.Web.UI.WebControls.TextBox. Is there a way to make the template add the controls to it's collection instead of just calling ToString() on them?
Note: I've also tried adding the textbox and label to the controls collection of the container which does the same thing.
Ok. So I tried a few things and I came up with an OK solution.
First, I tried to use methods in the data binding expression and then keep track of where in the container's Control collection the textbox or label would go. However, the CompiledTemplateBuilder (which is what .Net internally builds for ITemplates specified in mark up) put all of the markup before and after both binding expressions into one DataBoundLiteral control and the Control collection was already built when the method was called.
What did work was to create a new WebControl which serves as a place holder for the controls within the composite control. It has one property Control and when set, it add the control to it's Controls Collection.
public class FormItemPlaceHolder : WebControl, INamingContainer
{
public WebControl Control
{
get
{
if(Controls.Count == 0)
return null;
return Controls[0] as WebControl;
}
set
{
if (Controls.Count != 0)
Controls.Clear();
Controls.Add(value);
}
}
}
Then in the mark up, I create a control of this type and bind it's Control property to the correct property in the container.
<test:FormItem ID="fi" runat="server" Title="MyTitle" Text="My Text!">
<TestTemplate>
<i>
<test:FormItemPlaceHolder ID="ph" runat="server"
Control='<%# Container.Title %>' />
</i>
<br />
<test:FormItemPlaceHolder ID="ph2" runat="server"
Control='<%# Container.Text %>' />
</TestTemplate>
</test:FormItem>
Does anyone have a better solution?
The container should not define the controls, just the data.
It is in the markup that you should define the actual controls of the data, and assign them the values in from the container.
E.g.
public class TemplateContainer : UserControl
{
public string Text { get { return m_text; } }
public string Title { get { return m_title; } }
private string m_text;
private string m_title;
private FormItem m_item;
public TemplateContainer(FormItem item)
{
m_item = item;
}
}
And in the markup:
<test:FormItem ID="fi" runat="server" Title="MyTitle" Text="My Text!">
<TestTemplate>
<i><asp:Label runat="server" Text='<%# Container.Title) %>' /></i>
<br />
<asp:TextBox runat="server" Text='<%# Container.Text %>' />
</TestTemplate>
</test:FormItem>
If you are trying to create a composite control that does not require controls to be added in the markup, then why are you using a Template? If it is just for styling then perhaps creating your own Style object may be more effective?