Custom Panel didn't render well - asp.net

I'm trying to customize the rendering of an ASP.NET Panel in this way...
[DefaultProperty("ID")]
[ToolboxData("<{0}:NFormPanel runat=server></{0}:NFormPanel>")]
[Description("Aldammam panel.")]
[ParseChildren(false)]
[PersistChildren(true)]
public class NFormPanel : Panel, INamingContainer
{
protected override void RenderContents(HtmlTextWriter output)
{
var sb = new StringBuilder();
sb.AppendLine("<table class=\"con-table\" style=\"width: 100%;\">");
output.Write(sb.ToString());
if (HasControls())
{
this.RenderChildren(output);
}
sb.Clear();
sb.AppendLine("</table>");
output.Write(sb.ToString());
}
}
...but the output renders the panel controls first then renders the table, like this...
<div>
<input name="TextBox1" type="text" id="TextBox1">
<table class="con-table" style="width: 100%;">
</table>
</div>
I would like the child controls inside the table as in the example below...
<div>
<table class="con-table" style="width: 100%;">
<input name="TextBox1" type="text" id="TextBox1">
</table>
</div>

Use the render method instead:
protected override void Render(HtmlTextWriter output)
{
var sb = new StringBuilder();
sb.AppendLine("<table class=\"con-table\" style=\"width: 100%;\">");
output.Write(sb.ToString());
if (HasControls())
{
//Alternatively call base.Render() which renders the panel's DIV
this.RenderChildren(output); //renders inner children only without panel DIV
}
sb.Clear();
sb.AppendLine("</table>");
output.Write(sb.ToString());
}

Related

Display partial view results in modal dialog box

I have a textbox on my form:
<input type="text" class="input-group-field" id="draftSearchProducts" name="draftSearchProducts" placeholder="SearchProducts" />
In my controller I have the following:
[HttpGet]
public ActionResult SearchResults(string keywords, int queryLimit = 20, int offset = 0)
{
try
{
ProductSearchResults searchResults = new ProductSearchResults();
ComApiData<GetProductsDataConnector> productData = new ComApiData<GetProductsDataConnector>();
var products = productData.Connector.GetProductBySearch(new ProductRequestParameters()
{
Search = keywords,
LTPMerchantId = merchantId,
QueryLimit = queryLimit,
QueryOffset = offset
});
searchResults.ProductDetails = products.ToList();
return PartialView("_SearchResults", searchResults);
}
catch (Exception ex)
{
throw ex;
}
}
And there is a button on the form:
<a id="draftAddProduct" class="hollow button secondary"><i class="fa fa-plus"></i> Add Product</a>
Since I am new to this side of development, I need a little help. I need to wire up the button to take the value typed in the text call the SearchResults controller (located in a file called ProductsController.cs) and populate a modal dialog box with the results. I have a partial razor page:
#model Sauron.Models.Products.ProductSearchResults
#foreach (var product in Model.ProductDetails)
{
<tr>
<td class="imageColumn">
#if (product.Image != null)
{
<div class="ajax-image-load">
<input type="hidden" id="BlockImageID" value="#product.Image.ImageId" />
<input type="hidden" id="BlockImageWidth" value="89" />
<input type="hidden" id="BlockImageHeight" value="89" />
<input type="hidden" id="BlockImageLoaderGif" value="/images/loader-circle-basic.gif" />
</div>
}
</td>
<td>
#product.SKU
<input type="hidden" id="editID" name="editID" value="#product.ProductId" />
</td>
<td>#(product.Description != null ? product.Description.Name : product.ReceiptName)</td>
#*<td>#(product.ColorId != null ? product.)</td> we might want to gather the color object as a property of this search class model*#
<td>
#{
var textColor = "";
if((product.InventorySummary ?? 0) <= 0){
textColor = "red-text";
}
}
<span class="#textColor">#((product.InventorySummary ?? 0).ToString())</span>
</td>
<td>
#if (product.ProductType != null ? product.ProductType.Equals(ProductType.PACK) : false)
{
<span>#(product.PackQty != null ? string.Format("{0} {1}", product.PackQty.Value, product.ProductType.ToString()) : product.ProductType.ToString())</span>
}
else if (product.ProductType != null ? product.ProductType.Equals(ProductType.CASE) : false)
{
<span>#(product.PackQty != null ? string.Format("{0} {1}", product.PackQty.Value, product.ProductType.ToString()) : product.ProductType.ToString())</span>
}
else
{
<span>#(product.ProductType != null ? product.ProductType.ToString() : "")</span>
}
</td>
</tr>
}
that will display the results. I need to display the results of the _SearchResults.cshtml page in a modal box.
I want to call the SearchResults method from the values entered in the text box to display the results.
Anyone's help is appreciated.
The problem was I was calling the controller by the wrong name. Once I got the right name, it started working.
Code:
$('#draftAddProduct').click(function () {
var keyWord = $('#draftProductModal').val();
$('#draftProductModal').load("#Url.Action("SearchResults","Products")?keywords=chair");
});
You can find an answer for this question here:
Bootstrap Modal Dialog - Loading Content from MVC Partial View

how to avoid inline code in .aspx .ascx

I have a usercontrol (.ascx) like this:
<% if (HasAccessMediaPlans) { iPortletCounter++; %>
<div class="orange-portlet-box">
<div class="HomeModulePortletTitle">Plans</div>
<p>Create // Edit // Review</p>
</div>
<div style="clear: both;"></div>
<% } %>
where HasAccessMediaPlans is a variable defined in user control's code behind(.ascx.cs) and it's assigned in page load.
protected Boolean HasAccessMediaPlans = false;
protected void Page_Load(object sender, EventArgs e) {
HasAccessMediaPlans = SessionState.CurrentUser.HasModuleAccess(MediaString + " Plans");
}
My question is: how can I avoid inline server code embeded in <% %> at my usercontrol markup(.ascx) ?
You can wrap this piece of code with a server side container control (say <div id="wrapper" runat="server">) and on the server side assign its visibility properties in the wanted manner.
This avoids littering your .aspx/.ascx files with code and keeps code in the code-behind file.
<div class="orange-portlet-box" id="dvBox" runat="server">
<div class="HomeModulePortletTitle">
<a id="aLink">Plans</a>
</div>
<p>Create // Edit // Review</p>
</div>
<div style="clear: both;"></div>
In code behind
Boolean HasAccessMediaPlans = false;
protected void Page_Load(object sender, EventArgs e)
{
HasAccessMediaPlans = SessionState.CurrentUser.HasModuleAccess(MediaString + "Plans");
dvBox.Visible = HasAccessMediaPlans;
aLink.HREF = RootPath + "MediaPlanning/Default.aspx";
}

Return Different Views From MVC Controller

I've a MVC application, whose SharedLayout view(Master Page) gives user capability to search. They could search their order by Order No or By Bill no. So there are two option buttons the Shared View along with the textbox. Code is somewhat like this
#using (Html.BeginForm("Track", "Tracking", FormMethod.Post))
{
<div style="text-align: center">
<textarea cols="20" id="txtNo" name="txtOrderNo" rows="2" ></textarea>
</div>
<div style="text-align: center">
<input type="radio" name="optOrderNo" checked="checked" value="tracking" />Order No <input type="radio" name="optRefNo" value="tracking" />Ref No
</div>
<div style="text-align: center">
<input type="submit" value="Track" />
</div>
}
So it'll go to TrackingController and Track Method in it and return the view. It works fine for a single search as a View is associated with a controller's methods. It works fine but how could i conditionally return the other view based on the radio button selection.
What i come up with is this
[HttpPost]
public ActionResult Track(FormCollection form)
{
string refNo = null;
if (form["optRefNo"] == null)
{
string OrderNo = form["txtOrderNo"];
var manager = new TrackingManager();
var a = manager.ConsignmentTracking(OrderNo);
var model = new TrackingModel();
if (OrderNo != null)
model.SetModelForConsNo(a, consNo);
return View(model);
}
refNo = form["txtConsNo"];
return TrackByRef(refNo);
}
public ActionResult TrackByRef(string refNo)
{
//what ever i want to do with reference no
return View();
}
Kindly guide.
Thanks
View has an overload where the first parameter is a string. This is the name (or path) to the view you want to use, rather than the default (which is a view that matches the action's name).
public ActionResult TrackByRef(string refNo)
{
//what ever i want to do with reference no
return View("Track");
// or, if you want to supply a model to Track:
// return View("Track", myModel);
}

Jquery datepicker with entity framework

<form id="Form1" runat="server">
**<input type="text" id="DateInput" />**
<asp:Repeater ID="DataViewer" runat="server">
<ItemTemplate>
<div style='border: 1px; width: 600px; overflow-x: auto; overflow-y: hidden;'>
<div style='float: left;'>
<%# Eval("DriverName") %> </div>
</div>
</ItemTemplate>
</asp:Repeater>
this is my function:
protected void Page_Load(object sender, EventArgs e)
{
OrderDataRepository rep = new OrderDataRepository();
var results = rep.GetAllOrderData().Where(x => x.POD_DATE == ????????????????).
GroupBy(o => o.User).
Select(g =>
new
{
DriverId = g.Key.Id,
DriverName = g.Key.Name,
OrderCount = g.Count(),
OrderCountWhereNameIsNotNull =
g.Count(o => o.RECEIVE_NAME != null)
}).ToList();
DataViewer.DataSource = results;
DataViewer.DataBind();
}
at the moment i get all the results from the table,
i want to add Datepicker for jQuery http://keith-wood.name/datepick.html
<script src="Scripts/jquery.js" type="text/javascript"></script>
when user will pick a day it needs to load all the results for the day that the user picked
please show me how it should be done using jquery with entity framework
You'll need a function in your repository some thing like:
Function SelectOrdersByDate(date as string) as ienumerable(of Order)
Using yourcontext as new context
Dim query = yourcontext.Orders.Where(function(o) o.OrderDate = date).ToList
return query
End Using
End Function
Then call this function via ajax/jquery

ASP.NET: User control with access to the controls that it wraps

I have a bunch of occurrences of this kind of boilerplate code in my ASP.NET project.
<div class="inputfield">
<div class="tl">
<span class="tr"><!-- --></span>
<span class="ll"><!-- --></span>
<div class="lr">
<div class="cntnt">
<asp:TextBox .../>
</div>
</div>
</div>
</div>
As you may have guessed, everything in that snippet is pure boilerplate except for the innermost text field.
What is the best way to avoid such boilerplate in ASP.NET? In e.g. Django I would make a custom tag for it, as such:
{% boiler %}
<input ... />
{% endboiler %}
I was thinking that maybe I can create a user control, but all the tutorials on ASP.NET user controls that I've found are very simplistic and "self-closing", i.e. they are not aware of the contents of the tag. I need something along the lines of:
<Hello:MyControl>
<asp:TextBox .../>
</Hello>
So my question is the following: what's the best way to avoid the boilerplate?
You can use an ITemplate property. Thus, you can inject different content in different situations.
[PersistChildren(false), ParseChildren(true, "ContentTemplate")]
public partial class WebUserControl1 : System.Web.UI.UserControl
{
[System.ComponentModel.Browsable(false), System.Web.UI.PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate ContentTemplate { get; set; }
protected override void CreateChildControls()
{
if (this.ContentTemplate != null)
this.ContentTemplate.InstantiateIn(this);
base.CreateChildControls();
}
}
Put the asp:TextBox in your user control, along with the other html tags. Provide properties on your user control that match the properties of the text box, so that you would do something like this:
<Hello:MyControl ID="myControl" runat="server" Width="300px" MaxLength="30" />
and then the width and maxlength properties would just get transferred to the internal textbox.
You could also provide access to the textbox from the usercontrol and set all the properties in the code behind.
Create a class like this:
[PersistChildren(false), ParseChildren(true, "ContentTemplate")]
public class CustomContent:WebControl
{
[System.ComponentModel.Browsable(false), System.Web.UI.PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public ITemplate ContentTemplate { get; set; }
private PlaceHolder m_placeHolder;
protected override void CreateChildControls()
{
m_placeHolder = new PlaceHolder();
if (this.ContentTemplate != null)
this.ContentTemplate.InstantiateIn(m_placeHolder);
Controls.Add(m_placeHolder);
}
protected override void RenderContents(HtmlTextWriter writer)
{
writer.Write(#"<div class=""inputfield"">
<div class=""tl"">
<span class=""tr""><!-- --></span>
<span class=""ll""><!-- --></span>
<div class=""lr"">
<div class=""cntnt"">
");
base.RenderContents(writer);
writer.Write(#" </div>
</div>
</div>
</div>
");
}
}
This class isn't a "User Control" it's a "Server Control". You can do the same thing with a user control but you'll have issues with the designer. This will work in the designer.
And you can put markup like this in your ASPX:
<uc1:CustomContent runat="server" ID="content">
<asp:textbox runat="server"></asp:textbox>
</uc1:CustomContent>
don't forget the Register page declaration at the top of the aspx
<%# Register tagprefix="uc1" Assembly="Assembly where CustomContent is" Namespace="namespace where CustomContent is" %>
You can put whatever you want inside the uc1:CustomContent tags and it will render that boilerplate html around it. If you are curious about how ITemplate works, there are plenty of articles on msdn, etc.

Resources