I have the asp.net application where I am having the editable grid view with the edit,Delete,Add options. this grid having as usual Template fields. I have also a static Class that having static string variables. I want to keep these static variable's value as Header text of Template Field.
So I have imported my constant class's namespace by :
<%# Import Namespace="ConstantManagerNamespace" %>
Then I tried for same column:
1. <asp:TemplateField HeaderText=<%=ConstantManager.Name%>>
2. <asp:TemplateField HeaderText='<%=ConstantManager.Name%>'>
3. <asp:TemplateField HeaderText=<% ConstantManager.Name %>>
4. <asp:TemplateField HeaderText='<% ConstantManager.Name%>'>
all probable syntax to access my constant variable value but
I got Parser error:
Literal content ('<asp:TemplateField HeaderText=') is not allowed within a 'System.Web.UI.WebControls.DataControlFieldCollection'.
how to do this ?
The problem occurs because you are trying to embed server-side control/value inside another server-side control. That is not directly possible in asp.net, unless you use databinding or custom expression builder.
For your exact situation, you need to create a custom expression builder, which returns the value from your static class.
Final result should look something like this:
<asp:TemplateField HeaderText="<$ ConstantManager:Name >">
Which is absolutely allowed withing aspx file as long as you have defined the custom expression builder with "ConstantManager" prefix.
The actual example of creating the custom expression builder can be found here: ExpressionBuilder Class.
ADDITION:
Also, I think databinding will also work, but it seems to me not the exact solution for this kind of situation.
Just use this syntax in the aspx markup:
<asp:TemplateField HeaderText="<# ConstantManager.Name >">
And, on page load, call:
protected void Page_Load(object sender, System.EventArgs e)
{
this.DataBind();
}
Personally I don't like this solution because of the Page_Load part. Anyway, this does not need to have anything special declared/coded if compared to the custom expressions.
I hope this helps!
Its better to bind the static class varibles in the GridView RowDataBound Event,
check the Row type is Header ie.
if (e.Row.RowType == DataControlRowType.Header)
{
e.Row.Cells[0].Text = ConstantManager.Name;
}
Related
I have this error: "Object reference not defined for an instance of an object."
What I've tried was to create an instance of the class and, through it, try to access the gridview passing a DataSet to make the Bind.
The class is consumed via AJAX (AJAX.PRO)
Example of what I did:
public partial class Exemplo : InternalBasePage
{
[AjaxPro.AjaxMethod(AjaxPro.HttpSessionStateRequirement.Read)]
public static string SalvarRegra(JavaScriptArray DataRule, string NameRule)
{
Exemplo exemplo = new Exemplo();
DataSet ds = new DataSet();
exemplo.GRID.DataSource = ds;
}
You so called static class is NOT a web page, nor a web method.
If you want to add a web method to a existing web page, then do so, and that web method is then free to use that static class.
But, a general class, or in fact any class you build is just that - a class and hunk of code. But, as such it has really ZERO to do with a web page, or even a web method.
And it not clear why you would pass a gridView to such a static method, but you can.
I mean, in code it would be better to have say all your helper routines in a static class, and thus in code you could and would do this:
Say, on page load, fill out the grid view using that static class, like this:
Say my gv is this:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" cssclass="table" >
<Columns>
<asp:BoundField DataField="Fighter" HeaderText="Fighter" />
<asp:BoundField DataField="Engine" HeaderText="Engine" />
<asp:BoundField DataField="Thrust" HeaderText="Thrust" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:ImageField DataImageUrlField="ImagePath" HeaderText="Profile Pic"
ControlStyle-Width="150px" />
</Columns>
</asp:GridView>
So, say on page load I do this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridView1.DataSource = General.MyRst("SELECT * FROM Fighters");
GridView1.DataBind();
}
}
So, we get this:
So, in above, I used the static class General.MyRst (and that static class is bunch of general code routines that are rather handy).
Now, I suppose I could setup that static class to take a GridView as a parameter, say like this:
General.MyRst(GridView1, "SELECT * FROM Fighters";
Gee, saved one line of code. So the above static class is now loading up (manuplaiting the GV).
so it is VERY easy to have a static method to load or do whatever to a GV.
However, you are confusing that of say the above simple static method that loads up and manipulating the GV as opposed to calling a web method to do the same thing. That is a VAST VAST different issue and VAST VAST different goal. We don't want to confuse the above simple and easy demonstration of a static method manipulating a GV with that of calling a web method - they are VAST VAST different issues and goals here.
But then again, I just built a method that is now tied to the GridView type and class. With above, MyRst returns a data table - I can use it for quite much any combo box, listview, gridView - it don't matter.
But, if you going to make a web method call, that occurs from the client side page, and how do you propose to pass the GridView object? You don't have use of the GV object client side, and you don't have a post-back, so the class instance of GV does not exist at this point in time.
And if you going to do this from the web page class, such as the above one line static class that "manipulates" the GV?
You have to pass that GridView from the web page class - code behind. And any ajax call to the current page does not have any of the controls, or even use of the current web page class (to get at and use controls).
So, any static class that uses say the GV? It will have to be called from that web page - which is not a static class.
And while you CAN add static web methods to the current web page?
Keep in mind this:
Any web method, INCLUDING ones on the current web page will also be static, and do NOT have use of controls on the current page.
I suppose you could have the web method call return the rendered gridview, and inject that into the page, but I fail to see the advantage here.
So, the problem here is that both web methods to you say add to the current page - they are also static, and don't have use of any control on the current page. And even a static class - it also does not have use of the web page. and you not done a post back, so you still in hot water.
It not clear what you final goal here is, but I fail to see how attempting to use a static web method going to help you fill a gridview when that gridview is a server side object, and one you do NOT have use of until such time you do a post-back.
if the goal is to avoid a post-back? Then I would return json data, and use a client side grid. On the other hand, it is VERY easy to simple drop in a update-panel, and load up the grid that way, and you not suffer a full page post-back. And in most cases, you can (and should) say turn off view state for that GV to reduce the size of the grid re-load.
You can try a working grid example - I put the grid inside of a update panel, and thus when you edit values, the response time is near instant. But MORE important I fired up the browser tools, and to pop the editor in that GV - the size is a VERY tiny 7k in size.
As a result?
I used plain jane code behind, but get no browser re-plots, and response time is absolute instant. Absolute instant response time, and no messy browser re-loads should be your goal here. And that goal in most cases can be achieved without having to resort to a ajax call to load up that grid.
Try this working grid edit example here - try clicking on edit - use save button. I did not have to wire up a bunch of ajax calls, and the only js code I have was using a jquery.UI dialog to pop the div for editing - but the div is filled with code behind.
http://www.kallal.ca/WebSite11/WebForm2
Given the absolute instant response time of above? Then you can avoid a boatload of work, avoid world poverty, and not have to resort to ajax calls when working with a gridview.
All you should care about as a developer is that you not doing huge post-backs, and your not having to write a lot of code for this goal. So, you want fast, you want instant response, and you don't want or need much of any client side code to achieve this goal.
so, "WITH" a static method, you can manipulate a GV. But you can't FROM a static method. Well, I suppose you could if you put the GV into session, since a static method can use session.
I have a repeater in one of the sublayouts in Sitecore 6.6. rev 120918. Inside this repeater, I have a placeholder. On ItemDataBound, I assign a key with a GUID to it, and using Nick Wesselman's GetAllowedRendering pipeline, I am able to render the insert options for this.
The repeater code is very simple:
<asp:Repeater runat="server" ID="rptrTimelineItemsEdit" OnItemDataBound="rptrTimelineItemsEdit_OnItemDataBound">
<ItemTemplate>
<sc:Placeholder ID="scTimelineItemPlaceholder" Key="timelineitemcontent" runat="server" />
</ItemTemplate>
</asp:Repeater>
The Item Data bound is also pretty simple:
protected void rptrTimelineItemsEdit_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Item item = (Item)e.Item.DataItem;
Placeholder scTimelineItemPlaceholder = (Placeholder)e.Item.FindControl("scTimelineItemPlaceholder");
scTimelineItemPlaceholder.Key = "timelineitemcontent" + item.ID.ToString().ToLower();
}
}
Everything works up to this point. After I choose the sublayout I want to insert in the placeholder, it throws me an in the JS error popup. After inspecting in the chrome inspector, I see the error is:
Could not find the rendering in the HTML loaded from server PlaceholderChromeType.js:601
Sitecore.PageModes.ChromeTypes.Placeholder.Sitecore.PageModes.ChromeTypes.ChromeType.extend._frameLoaded
So - it would seem like that in the page reload, the sublayout renderings are happening before the repeater bindings, so it can't find the placeholder key.
I did some google, and found that there is a way to change the layout engine sequence using the layoutpageevent setting:
However, this didn't solve my problem. I'm out of ideas. Help!
Hi there Ive found a solution to this issue, it had me stumped as well.
It only occurs to placeholders that sit under a repeater.
Overwrite PlaceholderChromeType.js in Website\sitecore\shell\Applications\Page Modes\ChromeTypes\
With the one ive dropboxed (also available on the credit link below)
https://www.dropbox.com/s/7m99b8jgdz3cgl2/PlaceholderChromeType.
Your keys then have to have dynamic in them for it to work.
Example code:
protected void R1_ItemDataBound(Object Sender, RepeaterItemEventArgs e)
{
var p = e.Item.FindControl("andysplaceholder") as Placeholder;
p.ID = "Andy" + (e.Item.ItemIndex + 1);
p.Key = "dynamic" + p.ID;
}
<asp:repeater id="MyRepeater" runat="server" OnItemDataBound="R1_ItemDataBound">
<ItemTemplate>
<sc:placeholder runat="server" id="andysplaceholder" key="dynamicandysplaceholder" ></sc:placeholder>
</ItemTemplate>
</asp:repeater>
On top of this i do my repeater binding in the oninit method
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
and i set the web.config setting from preInit to load
<setting name="LayoutPageEvent" value="load" />
Although that might be overkill, I will revert today to page_load and preinit today and see if it still works.
Credit to Sitecore support and Mickey Rahman for this http://mickeyrahman.wordpress.com/2014/05/05/an-ode-to-sitecore-support/#respond
This should also work with the dynamic key apprach from Nick, you'll just have to make sure the keys generated by his code have dynamic in them
You have not implemented it in the way it's explained by Nick.
What you need to do is create a WebControl class for your Dynamic Placeholder.
That will ensure that things are processed in the same order as it would have with a 'real' Placeholder.
So the first thing I would do is make sure you do it in the same way as it's been described by Nick.
Then verify that it works with just 1 dynamic placeholder on the page.
Secondly, you should take a look at this blog post: Dynamic Placeholders and IExpandable
It explains how to deal with adding multiple dynamic placeholders in repeaters (and other controls).
He also thought that it had something to do with the change in the LayoutPageEvent, but it did not turn out to be that.
EDIT:
I've reproduced the issue and I highly doubt that you're going to solve it with this approach.
The placeholders are not loaded yet when the Page Editor is requesting their renderings after trying to add controls to them.
Even when you create the Placeholders in the OnInit (which is the earliest), it doesn't work.
If I get more time I'll try to look into it further.
Ruud referenced my blog post Dynamic Placeholders and IExpandable in his answer, and I think that he's definitely on the right track. I know that you haven't used dynamic placeholders in the way that I describe, however you are still creating placeholders dynamically.
I personally have never had any success with the LayoutPageEvent; which is why I decided to post about the use of IExpandable as it isn't something that's been highlighted that much.
You ought to create your placeholders in the Expand method and also expand them after you add them to the page. I would personally advise against using a Repeater to do so - add them to the controls collection or maybe to a normal ASP.Net PlaceHolder control.
public class YourSublayout : UserControl, IExpandable
{
public void Expand()
{
var myListOfItems = GetItems()
foreach (var item in myListOfItems)
{
var placeholder = new Placeholder { Key = "key" + item.ID.ToString() };
container.Controls.Add(placeholder); // add to a control container
placeholder.Expand();
}
}
}
Hopefully that should get you a bit further (if you haven't solved it already). Just keep in mind the other things I mention on my post, namely that the Expand method can be called before the control gets added to the page, and so getting your DataSource may break if you rely on getting it from the parent control.
I am trying to build a reusable control (ascx) that can be used in multiple aspx pages. I have a datasource in the control which has a SelectMethod. Id like to use the calling page name (minus the extension) as the name of the SelectMethod - which can be looked up elsewhere.
Not sure how I would access this information from the ascx page. Was hoping something like this pseudo-code would work:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" OldValuesParameterFormatString="original_{0}" SelectMethod="Parent.pagename()" TypeName="BlahBlah"></asp:ObjectDataSource>
Where pagename() is a function in the .ascx.cs file returning the parent aspx page name as a string which can be looked up as the SelectMethod elsewhere in the ObjectContextFacadeManager in the BLL (its a large behemoth application - only half of which I am aware of).
Cheers.
You can get the value you're looking for using the AppRelativeCurrentExecutionFilePath. To output it you may have to use code-behind, though, because using inline-script, such as:
SelectMethod="<%Request.AppRelativeCurrentExecutionFilePath%>"
Won't work as the attribute value of a control with runat="server" (IIRC).
So, on load, or some other event, you could set this programmatically:
Page_Load(object sender, EventArgs e) {
SelectMethod = System.IO.Path.GetFileNameWithoutExtension(
Request.AppRelativeCurrentExecutionFilePath);
}
Is there any way to directly access a field of class in the aspx page?
I have tried this:
In the aspx page I have added:
<form id="LoginForm" runat="server">
<asp:Label Text='<%# Eval("Test") %>' runat="server" ID="jym" />
</form>
and in the backend class of this page I have declared a property as:
private string test;
public string Test {
get {
return test;
}
set {
test = value;
}
}
This property is initialized in Page_Load() as: Test = "JYM";
But the problem is I am unable to see this value in the browser. The tag is rendered into <span/> but without any content.
What I am doing wrong?
Are you calling Page.DataBind() in Page_Load()?
You are using the # data binding operator in your embedded code block. The values that you bind to the control will only show after you have called DataBind() from either the control or the page (which will in turn call it for each control on the page).
If you only want to bind a value to that single label control you could just call jym.DataBind().
I would however suggest using a more descriptive name (id) for the Label control so it is clearer in the code about what is being databound.
See this page for more details.
UPDATE (extra info requested by OP in comment)
So you have 3 options:
1.
Call DataBind() as suggested above.
2.
Don't use a server side control for the label. Just use plain HTML and then you can use the following syntax:
<p><%= Test %></p>
3.
Set the value of the label in the code behind. For example in your page load you might have the following:
protected void Page_Load(object sender, EventArgs e)
{
jym.Text = Test;
}
You may want to use <%= this.Test%>. You can also do this.jym.Text=Test; in the Page Load evt.
I have a FindControl in OnLoad event to find my button on page i.e.:
protected override void OnLoad(EventArgs e)
{
DataBind();
control button = Page.FindControl("myButton");
}
on my aspx page I have
<asp:Button runat="server" ID="myButton" />
If I only have this, everything works, when I pass in the OnLoad, button is not null and I can execute what I want. The problem is when I add dynamic text in my aspx:
<asp:Button runat="server" ID="myButton" Text='<%# "Here is my dynamic text pulled from a XML" %>' />
Then the FindControl finds nothing and the button is null.
Adding a binding server tag on aspx isn't suppose to delay anything right? When I inspect the Page object I have some controls in Controls collection, but I'm unable to find myButton.
Any idea on what I am doing wrong?
EDIT
People seem to think that my code example is my real code but it isn't, So I use FindControl because I need to since I have nested controls and I cannot access it directly and I use binding because the dynamic text I'm putting is inside a ContentTemplate which I can override in other page aspx.
The question I asked was more specific to the fact that I have traced the problem where my FindControl returns null because a newly implement behaviour which is the binding.
Improving the code example isn't a solution or an explanation to the fact that if I put a <%# %> tag in my aspx page, the FindControl in the OnLoad event return null.
EDIT 2
the bind tag alone seems to not be the culprit but the DataBind() to populate them. Whether or not I have bind tag, putting DataBind() before the FindControl makes the myButton to be null. Correction in code example was made.
In here MSDN says that :
PreRender : Each data bound control whose
DataSourceID property is set calls its
DataBind method.
It looks like you're not using DataSourceID of your data bound control, but moving your FindControl code to PreRender event might help.
The Page.FindControl() method will only search the imediate collection of controls that are associated with Page. It will not recurse down the entire control tree, so if your button is contained within another control it will not be found. You would need to call the FindControl method on the containing control.
If you want to access a button on your page, you can directly refer to the button as -
this.myButton
And as far as assigning values is concerned, you can do it like this in your server code -
this.myButton.Text = "Dynamic Text";
<%# xyz %> is only used when you are databinding the controls, for e.g. in a DataGrid, GridView, etc.
In your override dont you want to call base.OnLoad(e) in your method first ?