ASP.NET: Can you use server tags to embed C# or VB.NET expressions into a Javascript function? - asp.net

I have an enum called SiteTypes that contains several values that are all bound to a dropdown list. On the client side, I need to check this dropdown to see if the selected value is one of those enum values. I don't want to hardcode the value of the enum in the script in case it needs to change, so I want to use a server tag to get it directly from the enum itself. Conecptually, I would like to do this:
function SiteIdChanged() {
var x = "<%=SiteTypes.Employee %>";
}
The way I am doing it now is created a protected property in the codebehind that returns that specific enum value and am doing this:
function SiteIdChanged() {
var x = "<%=EmployeeSiteTypeValue %>";
}
I don't like that, though, because I have to create a special property on every page that I need to do such a check.
Is there a way to do what I want here?

Are you getting a "xxx is inaccessible due to its protection level" error when you compile or run the page? enums are public by default, classes are not. My guess is that you've defined your enum inside your page's class and you aren't explicitly marking it with the 'public' access modifier. Explicitly mark it as public or move it outside of the class and see what happens. If you're planning on using it on lots of pages you should stick the enum definition in in a file in the App_Code folder of your project.

If you don't like your current implementation I would consider using a PageMethod to compare the dropdown selection to the enum value. This approach will probably be cleaner, as you can do most of the logic server-side.
Here's a tutorial on PageMethods:
http://blogs.microsoft.co.il/blogs/gilf/archive/2008/10/04/asp-net-ajax-pagemethods.aspx

As long as your enum is marked public, you can just go with your first option. There's no need to put a property on every single page you want to retrieve the value from.
That approach is really the simplest solution for writing out server side values in your JavaScript.

You can use the Enum.IsDefined Method this well tell you if the selected value from the dropdown is actually part of your enum.
Enum.IsDefined(typeof(MyEnum), myValue)
http://msdn.microsoft.com/en-us/library/system.enum.isdefined.aspx

Related

How to get the generated Unique ID prefix for a page's controls

As we know, ASP.NET WebForms will generate a Unique ID (as well as name) to a control to prevent collisions in the control heirarchy. Let's say we have a TextBox control with an assigned ID of "MyTextBox" in the markup. If this textbox is on a page with a Master Page then the TextBox control will be given a Unique ID of "ctl00$MainContent$MyTextBox" or something similar.
What I want to know is, for a given page, is it possible to know what the prefix WILL BE? In my above example I would like to know all controls I create on that page will be assigned with a prefix of "ctl00$MainContent$". I have examined the Page object and I cannot find an easy way to extract this information. Note: inspecting already existing controls on the page (like the TextBox) isn't an option. I simply need to know, at run time, what the prefix would be.
-- EDIT: Why do I need to do this? --
Ultimately I am trying to solve the problem that this post illustrates:
ASP.NET 4.5 TryUpdateModel not picking Form values in WebForm using Master-Page
I'm using the ModelBinding features introduced in ASP.NET 4.5. Problem is, as the above post points out, is that the name value collection found in the form will NOT match up with your model's properties. The built-in FormValueProvider expects a one-to-one match with the form key (name) and the model's properties. Unfortuantely, the form's keys will have the typical "ctl00$MainContent$" prefix to the names.
I have a semi-working solution where I created a custom IValueProvider that compares the end of the form key with the model's property. This works 95% of the time, but there's always a chance of multiple hits.
Ideally, and this is what I'm trying to figure out, if I could determine WHAT the prefix is I can then prefix that the IValueProvider's passed in key, look for that in the form and find the exact match.
So that is why I'm wondering if there's any way to know what the prefix should be for a given page.
The real answer is to simply code in such a way that you never have to know this information. that might not always be easy - but that's quite much what we do. You can certainly in code behind get/grab the "id" of the given button.
so for example, I become VERY tired of having to wire up a little toast message all over the place. So, I put in a little js routine (in the master page).
But I did need the client ID of a given control.
Well, the code behind needed (wants) to place the toast message next to whatever I clicked on.
So my server side "toast" message caller of course will after the server side code is done does the common "script" inject that will run when the page finally makes it final trip back down to the browser, displays the page, and then of course runs that script I injected.
So, my server side code does this:
MyToast2(Me, btnUpdate.ClientID.ToString, "Update ok!", "Settings changed")
So note how I get/grab/pass the "ID" of the control that the server is going to render. You can use ClientID to get the the final "ID" used for that control in code behind.
So, that btnUpdate is just a simple button placed on the web form. But who cares what super ugly "ID" the server assigns. i just need the "id" of the control so the JavaScript client side can pick up that control - and thus know/get/have the position of the control, and thus I get this result:
Or if I am some place else - again I can call that js routine - and that routine needs the current control. so might have this:
So, I can now just call a routine and pop up a message - not have to write any new js code for the gallzion notices and little pops I have all over the place.
so the little javaScript routine of course does this:
function toastcallm(cntrol, h, t, d) {
var cmd = $('#' + cntrol);
var mypos = cmd.position();
bla bla bla
But only important was that I get/determine and pass the used server "client" id to that routine - I don't really care what it is , or how to see, or how to list them out. I suppose a better jQuery selector or using wild card might work - but I really don't want to know the control ahead of time - but only that I can get the clientID used when I need it.
I simply write code that assumes somewhere along the way when I need such a client id, I simply get it and use it.
So, on the server side? Well, we always build and write code based on the control ID, but you want to get your hands on the actual id? Then you can use in the server code behind:
btnUpdate.ClientID.ToString
(ie: somecontrol.ClientID).

User Control, Shared Property, setting label text

I usually make user controls containing forms for adding and editing data for a particular table in my database. I then show or hide these controls as the user clicks "edit" buttons, etc. It's common practice (for me) to put properties in the code-behind, that are used for setting the ID of the item being edited, into a hidden label on the page, and of course leaving it blank for new items being inserted. I usually only use C#, however, this time around I have to use VB.NET.
So in C# I would do the following:
public static int EditID
{
get
{
return Convert.ToInt32(lblEditID.Text);
}
set
{
lblEditID.Text = value;
}
}
..and then when the user, say, clicks an "edit" link from a gridview, I would
//set the ID of the corresponding record, something like this:
MyUserControl.EditID = MyGridView.SelectedDataKey[0];
Cool. So now I need to do this in VB.NET, and here's my code:
Public Shared Property EditID As Integer
Get
Return Convert.ToInt32(lblEditID.Text)
End Get
Set(value As Integer)
lblEditID.Text = value
End Set
End Property
but I get a syntax error that says: "Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class.", highlighting the lblEditID for both the getter and setter.
I can't find any other SO questions about this, and I have Google'd just about every permutation of keywords I can think of, so this must be something really stupid.
What am I doing wrong here?
EDIT: Yes I realize I could just use a Session variable instead of the label, but I would still like to know why this doesn't work and how I could make it work with a label.
You don't want a Shared property for this. lblEditID is a label that exists in an instance of a WebForm class:- it can't exist until an instance of this class has been created, hence the error.
I don't really understand how the C# worked as this should be the same but I'm not a C# expert.
If you remove the Shared keyword it will work as you want I believe

ASP.NET: Is it possible to create dynamically-named Javascript functions without using .NET code (ie, VB.NET or C#)?

I have a custom user control (ascx) that contains a textbox and a Javascript-based counter to let the user know many characters they have left to type. In this control is the following:
function GetTextBox() {
return document.getElementById("<%=txNotes.ClientID %>");
}
This worked fine when we only had one instance of this user control on the page, but now we have to support multiple. As you know, having multiple instances of this control on a page will result in multiple GetTextBox() functions, only the last of which will be called no matter what. To support multiple instances, I use this:
if (!string.IsNullOrEmpty(TextBoxName) && !Page.ClientScript.IsClientScriptBlockRegistered(TextBoxName))
{
string Script = string.Format("function Get{0}Notes() {{ return document.getElementById(\"{1}\"); }}",
TextBoxName, txNotes.ClientID);
Page.ClientScript.RegisterClientScriptBlock(GetType(), TextBoxName, Script, true);
}
TextBoxName is a public usercontrol property, so if the developer passes Employee through, it will generate a Javascript function called GetEmployeeNotes(). This works greate because now we can have a unique GetNotes() function.
However, I don't like how it's hardcoded into the codebehind. I would like a markup-based solution for this, something that doesn't require a rebuild of the project in case I want to change the Javascript. Does anyone know of a way to do this?
Edit: I've already thought of creating a separate .js file that I could read with a text reader, but that sounds a bit hacky and I'd like to avoid that if at all possible.
Edit 2: Guard's answer below would work, but I don't want to go that route for the reason I gave beneath his answer. If no one can offer another way to do what I want to do, I will most likely mark his as the answer since it technically does exactly what I am asking.
I'm not a .NET specialist, but isn't it working as a preprocessor?
Isn't it legal to write
function Get<%=Name %>Notes() {...}
?
Why not use a generic function and just pass the id of the corresponding textbox? As in: GetNotes(thisTextBoxId) {...}. Not only would that deal with your problem but also is more DRY.

Is it possible to have WPF/SL4 perform operations on a property binded to another control?

Using SilverLight, one can bind the value of a control to a property from a datacontext. That's fine.
It is possible to use StringFormat along with the binding declaration to format the value. Again, that's cool!
However, I can't find a way to have the binding with some operation done to it before it gets displayed. I know I can code an IConverter but I was looking for something purely in XAML if that exists. I could also add a property to the class that returns the data in the correct way, but still what would happen if you don't have the source of the class?
For example, let's say I have this class for my datacontext (properly setup with notification and the like):
public class Info
{
public int SomeValue {...} // Value from 0 to 15
}
I would like to have a binding that would display 45 instead of 15 where the binding would be declared something like {Binding SomeValue, Operation="*3"}
Is there something like this in the .NET world (either from MSoft or OpenSource)?
found the link I was talking about.
Still, Charles Petzold also suggest to rather use a ValueConverter, even though some arithmetics is possible in pure XAML

React to change on a static property

I'm re-writing an MXML item renderer in pure AS. A problem I can't seem to get past is how to have each item renderer react to a change on a static property on the item renderer class. In the MXML version, I have the following binding set up on the item renderer:
instanceProperty={callInstanceFunction(ItemRenderer.staticProperty)}
What would be the equivalent way of setting this up in AS (using BindingUtils, I assume)?
UPDATE:
So I thought the following wasn't working, but it appears as if Flex is suppressing errors thrown in the instanceFunction, making it appear as if the binding itself is bad.
BindingUtils.bindSetter(instanceFunction, ItemRenderer, "staticProperty");
However, when instanceFunction is called, already initialized variables on the given instance are all null, which was the cause of the errors referenced above. Any ideas why this is?
You have 2 options that I am aware of:
Option 1
You can dig into the code that the flex compiler builds based on your MXML to see how it handles binding to static properties. There is a compiler directive called -keep-generated-actionscript that will cause generated files to stick around. Sleuthing through these can give you an idea what happens. This option will involve instantiating Binding objects and StaticPropertyWatcher objects.
Option 2
There is staticEventDispatcher object that gets added at build time to classes containing static variables see this post http://thecomcor.blogspot.com/2008/07/adobe-flex-undocumented-buildin.html. According to the post, this object only gets added based on the presence of static variables and not getter functions.
Example of Option 2
Say we have a class named MyClassContainingStaticVariable with a static variable named MyStaticVariable and another variable someobject.somearrayproperty that we want to get updated whenever MyStaticVariable changes.
Class(MyClassContainingStaticVariable).staticEventDispatcher.addEventListener(
PropertyChangeEvent.PROPERTY_CHANGE,
function(event:PropertyChangeEvent):void
{
if(event.property == "MyStaticVariable")
{
someobject.somearrayproperty = event.newValue as Array;
}
});
I think you need to respond to the "PropertyChanged" event.
If you're going to do that, use a singleton instead of static. I don't think it will work on a static. (If you have to do it that way at all, there are probably a couple ways you could reapproach this that would be better).
var instance:ItemRenderer = ItemRenderer.getInstance();
BindingUtils.bindProperty(this, "myProperty", instance, "theirProperty");
After fiddling with this for a while, I have concluded that this currently isn't possible in ActionScript, not even with bindSetter. It seems there are some MXML-only features of data bindings judging by the following excerpt from the Adobe docs (though isn't it all compiled to AS code anyways)?
You cannot include functions or array
elements in property chains in a data
binding expression defined by the
bindProperty() or bindSetter() method.
For more information on property
chains, see Working with bindable
property chains.
Source: http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_7.html
You can create a HostProxy class to stand in for the funciton call. Sort of like a HostFunctionProxy class which extends from proxy, and has a getProperty("functionInvokeStringWithParameters") which will invoke the function remotely from the host, and dispatch a "change" event to trigger the binding in typical [Bindable("change")] Proxy class.
You than let the HostProxy class act as the host, and use the property to remotely trigger the function call. Of course, it'd be cooler to have some TypeHelperUtil to allow converting raw string values to serialized type values at runtime for method parameters (splitted by commas usually).
Example:
eg.
var standInHost:Object = new HostFunctionProxy(someModelClassWithMethod, "theMethodToCall(20,11)");
// With BindingUtils.....
// bind host: standInHost
// bind property: "theMethodToCall(20,11)"
Of course, you nee to create such a utlity to help support such functionality beyond the basic Flex prescription. It seems many of such (more advanced) Flex bindings are usually done at compile time, but now you have to create code to do this at runtime in a completely cross-platform Actionscript manner without relying on the Flex framework.

Resources