Scriptcontrol - bind client & server properties - asp.net

Is it possible to bind properties on the client and server side in Scriptcontrol, so when I set property in javascript, change will be visible also in code behind and when I set property in code behind, change will be visible in javascript?
I can't get it work like above - it is set initially, when I set property where scriptcontrol is declared, but when I change it later it is still the same as before...
EDIT: I try to do a ProgressBar for long postbacks in our ASP.NET application. I have tried many options but none works for me... I want to set progress value in code behind and has it updated in view during long task postback.
Code for ScriptControl:
C#:
public class ProgressBar : ScriptControl
{
private const string ProgressBarType = "ProgressBarNamespace.ProgressBar";
public int Value { get; set; }
public int Maximum { get; set; }
protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
this.Value = 100;
this.Maximum = 90;
var descriptor = new ScriptControlDescriptor(ProgressBarType, this.ClientID);
descriptor.AddProperty("value", this.Value);
descriptor.AddProperty("maximum", this.Maximum);
yield return descriptor;
}
protected override IEnumerable<ScriptReference> GetScriptReferences()
{
yield return new ScriptReference("ProgressBar.cs.js");
}
}
Javascript:
Type.registerNamespace("ProgressBarNamespace");
ProgressBarNamespace.ProgressBar = function(element) {
ProgressBarNamespace.ProgressBar.initializeBase(this, [element]);
this._value = 0;
this._maximum = 100;
};
ProgressBarNamespace.ProgressBar.prototype = {
initialize: function () {
ProgressBarNamespace.ProgressBar.callBaseMethod(this, "initialize");
this._element.Value = this._value;
this._element.Maximum = this._maximum;
this._element.show = function () {
alert(this.Value);
};
},
dispose: function () {
ProgressBarNamespace.ProgressBar.callBaseMethod(this, "dispose");
},
get_value: function () {
return this._value;
},
set_value: function (value) {
if (this._value !== value) {
this._value = value;
this.raisePropertyChanged("value");
}
},
get_maximum: function () {
return this._maximum;
},
set_maximum: function (value) {
if (this._maximum !== value) {
this._maximum = value;
this.raisePropertyChanged("maximum");
}
}
};
ProgressBarNamespace.ProgressBar.registerClass("ProgressBarNamespace.ProgressBar", Sys.UI.Control);
if (typeof (Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
I'll appreciate any way to implement this progress bar...

Personally, I do this often using hidden fields.
Bear in mind that hidden fields are not secure and may have other downfalls, since they don't actually hide their value, just simply do not display it.
ASPX Markup
<asp:HiddenField ID="hiddenRequest" runat="server" ClientIDMode="Static" />
ASPX.CS Code behind
public string HiddenRequest
{
set
{
hiddenRequest.Value = value;
}
get
{
return hiddenRequest.Value;
}
}
Page JAVASCRIPT (with jQuery)
$('#hiddenRequest').val('MyResult');
This way, I can access the same field using one variable as such, accessed both from client side and server side.

Related

Caliburn Micro: How to add text to the bottom of a list box and display it

I'm trying to figure out how to add text to the bottom of a list box and display it. In WPF with code behind, I would grab the ScrollViewer and manipulate it, but I can't figure out how to do it with Caliburn...
You have a couple options.
1) In your ViewModel you can call GetView and cast it to your view type and get a reference to the ScrollViewer. Something like:
var myView = this.GetView() as MyView;
var myScrollView = myView.MyScrollView;
That works fine but isn't ideal if you're trying to not couple the view to the view model.
Option 2) is to implement IResult, see docs here.
public class ScrollViewResult : IResult
{
public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
private ScrollViewResult ()
{
}
public void Execute (ActionExecutionContext context)
{
var view = context.View as FrameworkElement;
var scrollViewer = FindVisualChild<ScrollViewer>(view);
//do stuff to scrollViewer here
Completed (this, new ResultCompletionEventArgs { });
}
private static TChildItem FindVisualChild<TChildItem> (DependencyObject obj)
where TChildItem : DependencyObject
{
for (var i = 0; i < VisualTreeHelper.GetChildrenCount (obj); i++)
{
var child = VisualTreeHelper.GetChild (obj, i);
if (child != null && child is TChildItem)
return (TChildItem)child;
var childOfChild = FindVisualChild<TChildItem> (child);
if (childOfChild != null)
return childOfChild;
}
return null;
}
//this isn't required of course but comes in handy for
//having a static method and passing parameters to the
//ctor of the IResult
public static IResult DoSomething ()
{
return new ScrollViewResult ();
}
Then you can call it like:
public IEnumerable<IResult> SomeAction()
{
yield return ScrollViewResult.DoSomething();
}

Enable Always on Top For Caliburn Managed Window

I have the following ViewModel and I am using Caliburn Micro. The IWindowManager instance is properly resolved and all of the code works. As indicated by the TODO comment, I need to get a reference to the current window so I can toggle the AlwaysOnTop attribute. How can I do that?
namespace CaliburnWizardPlay
{
[Export(typeof(DropWindowViewModel))]
public class DropWindowViewModel : PropertyChangedBase, IHaveDisplayName
{
private readonly IWindowManager windowManager;
[ImportingConstructor]
public DropWindowViewModel(IWindowManager windowManager)
{
this.windowManager = windowManager;
}
public string DisplayName
{
get { return "Main Window"; }
set { }
}
public bool AlwaysOnTop
{
get { return Settings.Default.DropWindowAlwaysOnTop; }
set
{
Settings.Default.DropWindowAlwaysOnTop = value;
Settings.Default.Save();
NotifyOfPropertyChange(() => AlwaysOnTop);
//todo: toggle the AOT attribute of the window
}
}
public void FileDropped(DragEventArgs eventArgs)
{
if (eventArgs.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] droppedFilePaths = eventArgs.Data.GetData(DataFormats.FileDrop, true) as string[];
foreach (string path in droppedFilePaths)
{
MessageBox.Show(path);
}
windowManager.ShowWindow(new WizardViewModel());
}
}
}
}
You can use the settings parameter of the ShowWindow method to set any property (e.g. Topmost) on the created window with a dictionary containing propertyname-value pairs:
windowManager.ShowWindow(new WizardViewModel(),
settings: new Dictionary<string,object> { {"Topmost", AlwaysOnTop} });
If you want to change the Topmost property of the already created window I see three options (in the order of preference):
Create an AlwaysOnTop property on the WizardViewModel and store the viewmodel in a private field and delegate the AlwaysOnTop to the WizardViewModel:
private WizardViewModel wizardViewModel;
public void FileDropped(DragEventArgs eventArgs)
{
//...
wizardViewModel = new WizardViewModel()
windowManager.ShowWindow(wizardViewModel);
}
public bool AlwaysOnTop
{
get { return Settings.Default.DropWindowAlwaysOnTop; }
set
{
//...
if (wizardViewModel != null)
wizardViewModel.AlwaysOnTop = value;
}
}
And in your view you can bind the WizardViewModel's AlwaysOnTop property to the window's TopMost property.
You can use the Application.Windows to retrieve the window. E.g. set the Name property of the created Window with the settings dictionary and then:
windowManager.ShowWindow(new WizardViewModel(),
settings: new Dictionary<string,object>
{ {"Topmost", AlwaysOnTop}, {"Name", "WizardWindow"} });
public bool AlwaysOnTop
{
get { return Settings.Default.DropWindowAlwaysOnTop; }
set
{
//...
var wizardViewModel = Application.Current.Windows.OfType<Window>()
.SingleOrDefault(w => w.Name == "WizardWindow");
if (wizardViewModel != null)
wizardViewModel.AlwaysOnTop = value;
}
}
Derive from the WindowManager and register it in your Bootstrapper and then you can override the CreateWindow, EnsureWindow etc. methods to store the created windows somewhere set the additional properties etc.

ASP.NET custom controls - custom property doesn't hold the assigned value on postaback

I have a custom asp-net control that inherits from another one and its works as expected, though the properties are only set properly if i code them in the markup directly, so for instance if i need set a property at runtime that is some dynamic value, this value is never set or somehow lost.
Here's the markup code:
<!--related form-->
<fw:advancedformdisplay id="formDisp" runat="server" captchaenabled="true" EmailEnabled="true" EnableViewState="true" captchaprivatekey="xxxxxxxxxxxxxxxxxxxx" captchapublickey="xxxxxxxxxxxxx" captchatheme="white" SourceType="MenuItem" SourceMainId="Auto">
</fw:advancedformdisplay>
This is the code of the control:
[DefaultProperty("CaptchaEnabled"),ToolboxData("<{0}:AdvancedFormDisplay runat=server></{0}:AdvancedFormDisplay>"), Description("This is an enhanced FormDisplay control that inlcudes Googles Captcha control is enabled")]
public class AdvancedFormDisplay :SiteBuilder.WebControls.FormDisplay
{
bool _CaptchaEnabled = false, sendEmail = false;
string captchaErrorMessage = "The verification code entered is not valid. Please try again!";
RecaptchaControl captchaControl = null;
string captchaPrivateKey = "", captchaPublicKey = "", captchaTheme = "clean";
string originalFormHtml = string.Empty;
string afterText = string.Empty, beforeText = string.Empty;
Literal litHtmlForm = null;
string captchaErrorClass = "errorCaptcha";
public string EmailBeforeText
{
get { return beforeText; }
set { beforeText = value; }
}
public string EmailAfterText
{
get { return afterText; }
set { afterText = value; }
}
public string CaptchaErrorClass
{
get { return captchaErrorClass; }
set { captchaErrorClass = value; }
}
public bool CaptchaEnabled
{
get { return _CaptchaEnabled; }
set { _CaptchaEnabled = value; }
}
public bool EmailEnabled
{
get { return sendEmail; }
set { sendEmail = value; }
}
public string CaptchaErrorMessage
{
get { return captchaErrorMessage; }
set { captchaErrorMessage = value; }
}
/// <summary>
/// red,white,blackglass,clean
/// </summary>
public string CaptchaTheme
{
get { return captchaTheme; }
set { captchaTheme = value; }
}
public string CaptchaPrivateKey
{
get { return captchaPrivateKey; }
set { captchaPrivateKey = value; }
}
public string CaptchaPublicKey
{
get { return captchaPublicKey; }
set { captchaPublicKey = value; }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
public override void OnSaved(FormDisplayEventArgs e)
{
//If captcha control is enabled we need to adda bit of code to redirect form properly
if (CaptchaEnabled && e.Redirect && !e.SendMail)
{
//Do Stuff
}
if(sendEmail)
{
//Send email
}
base.OnSaved(e);
}
public override void OnSaving(FormDisplayEventArgs e)
{
if (CaptchaEnabled)
{
//Validate and do stuff
}
base.OnSaving(e);
}
}
And then in my asp.net page that is using control, created by markup code, in the Page_Load() i try to assign some values to some properties and and the values aren't set properly, meaning that if i have set for isntance, the property EmailBeforeText = "somthing" this value will not be assigned..
protected void Page_Load(object sender, EventArgs e)
{
//2: Get the language of menuitem - Based on current culture setting (for by dropdownbox - change logic)
try
{
currentCulture = Thread.CurrentThread.CurrentCulture.ToString();
// Redirect if domain does not match rootnode.
DomainChecker.CheckURL(this.Request, this.Response, currentCulture);
if (footerArticle != null)
footerArticle.SourceMenuId = Digimaker.Config.Custom.Get("FooterID_" + currentCulture).ToString();
}
catch
{
currentCulture = "en-GB";
if( footerArticle != null )
footerArticle.SourceMenuId = Digimaker.Config.Custom.Get("FooterID_" + currentCulture).ToString();
}
Any ideas what i'm missing here?
Thanks a lot for your reading!
Regards,
byte_slave
short answer: use viewstate to persist your custom values!
Understanding ASP.NET ViewState whitepaper (see example with NavigateUrl)
edit: as reading the white-paper is obviously a really hard thing:
Each control is responsible for storing its own state, which is
accomplished by adding its changed state to its ViewState property.
The ViewState property is defined in the System.Web.UI.Control class,
meaning that all ASP.NET server controls have this property available.
(When talking about view state in general I'll use lower case letters
with a space between view and state; when discussing the ViewState
property, I'll use the correct casing and code-formatted text.)
If you examine the simple properties of any ASP.NET server control
you'll see that the properties read and write directly to the view
state. (You can view the decompiled source code for a .NET assembly by
using a tool like Reflector.) For example, consider the HyperLink Web
control's NavigateUrl property. The code for this property looks like
so:
public string NavigateUrl
{
get
{
string text = (string) ViewState["NavigateUrl"];
if (text != null)
return text;
else
return string.Empty;
}
set
{
ViewState["NavigateUrl"] = value;
}
}
As this code sample illustrates, whenever a control's property is
read, the control's ViewState is consulted. If there is not an entry
in the ViewState, then the default value for the property is returned.
When the property is assigned, the assigned value is written directly
to the ViewState.

When can I set default values for properties on server a control?

I have written the following override for the DataFormatString in my BoundField derived control, yet the field is still formatted as a plain number. I assume that this is because the formatting code isn't calling the DataFormatString property but using the private _dataField field. I would like set the base property in my override, but I want to do so based on a declarative FormatType enum property that will determine which default format string to use. Where could I do this?
public override string DataFormatString
{
get
{
var baseString = base.DataFormatString;
if (!string.IsNullOrWhiteSpace(baseString))
{
return FormatStrings.Currency;
}
return baseString;
}
set
{
base.DataFormatString = value;
}
}
EDIT: It turns out declarative property values are set when the control is built by it's parent, so it's pretty safe to assume they won't be properly used until after this phase of the page life cycle. This is what I actually wanted to know.
You can add the DefaultValue attribute at the top of the method:
[DefaultValue(false)]
public bool SomeCondition
{
get { return someCondition; }
set { someCondition = value; }
}
It looks like the parameterless constructor is the best place to do this. I wanted to set some properties to default values based on other properties, but I realised it wasn't necessary if I determined these defaults when needed, versus in the property getters. E.g:
public BoundReportField()
{
_formatType = FieldFormatTypes.String;
}
protected virtual string GetDefaultFormatString(FieldFormatTypes formatType)
{
var prop = typeof(FormatStrings).GetProperty(formatType.ToString()).GetValue(null, null);
return prop.ToString();
}
protected virtual IFormatProvider GetFormatProvider(FieldFormatTypes formatType)
{
var info = (CultureInfo)CultureInfo.CurrentCulture.Clone();
info.NumberFormat.CurrencyDecimalDigits = 0;
info.NumberFormat.CurrencySymbol = "R";
info.NumberFormat.CurrencyGroupSeparator = ",";
info.NumberFormat.CurrencyDecimalSeparator = ".";
return info;
}
private FieldFormatTypes _formatType;
public virtual FieldFormatTypes FormatType
{
get { return _formatType; }
set
{
_formatType = value;
}
}
protected override string FormatDataValue(object dataValue, bool encode)
{
var formatString = DataFormatString;
var formatProvider = GetFormatProvider(_formatType);
if (string.IsNullOrWhiteSpace(formatString))
{
formatString = GetDefaultFormatString(_formatType);
}
ApplyFormatStyles(_fieldCell);
var retString = string.Format(formatProvider, formatString, dataValue);
return retString;
}

Error messages in ASP.NET with jQuery UI

I've been using my own Error reporting module which was combination of simple c# and jQueryUI Dialog. Problem is that once error or success occurs i do write it's value to session. It does work pretty good on pages with Responce.Redirect on error but not on pages where i catch an error and then return to same form.
My question is why does session which added pre-postback fails to load in pages where i have return statement on some condition.
And if there another way to save errors and success message except in session ? Maybe global variables or something like that ...
CODE EXAMPLES
this is Error class
public static string getMessage()
{
HttpContext c = HttpContext.Current;
string messageType = "";
if (c.Session["errorMessage"] != null)
{
messageType = "errorMessage";
}
else if (c.Session["successMessage"] != null)
{
messageType = "successMessage";
}
if (!string.IsNullOrEmpty(messageType))
{
string[] messageBody = c.Session[messageType].ToString().Split('|');
StringBuilder userMessageSb = new StringBuilder();
userMessageSb.Append(string.Format("<div id=\"{0}\" title=\"{1}\">{2}</div>", messageType, messageBody[0], messageBody[1]));
// fix so message will not re-appear
c.Session.Remove(messageType);
messageType = userMessageSb.ToString();
}
return messageType;
}
public static void setSuccess(string successMessage)
{
HttpContext.Current.Session["successMessage"] = setMessage("success", successMessage);
}
public static void setError(string errorMessage)
{
HttpContext.Current.Session["errorMessage"] = setMessage("error", errorMessage);
}
private static string setMessage(string messageTitle, string messageBody)
{
return string.Format("{0}|{1}", messageTitle, messageBody);
}
i set message like this prior to redirect or return
Errors.setError(my error is");
i get error on bottom of my masterpage like this
<%= Errors.getMessage() %>
and this is JS
$(function () {
$("#errorMessage").dialog("destroy");
$("#successMessage").dialog("destroy");
if ($("#errorMessage").length != 0) {
$("#errorMessage").dialog({
modal: true,
height: 300,
width: 400,
buttons: {
Ok: function () {
$(this).dialog('close');
}
}
});
}
if ($("#successMessage").length != 0) {
$("#successMessage").dialog({
modal: true,
height: 300,
width: 400,
buttons: {
Ok: function () {
$(this).dialog('close');
}
}
});
}
});
There is a possibility that <%= Errors.getMessage() %> executes before you call Errors.setError(my error is") in case when you are not redirecting.
Hope below answer helps.
Create a property in your master page code behind
public string MessagePlaceholder
{
get { return messagePlaceholder.InnerHtml; }
set { messagePlaceholder.InnerHtml = value; }
}
Replace <%= Errors.getMessage() %> with a div place holder like below
<div id="messagePlaceholder" runat="server"></div>
And here is your setError method
public static void setError(string errorMessage, bool redirecting)
{
HttpContext.Current.Session["errorMessage"] = setMessage("error", errorMessage);
if (!redirecting)
{
((HttpContext.Current.Handler as System.Web.UI.Page).Master as YourMasterPageType).MessagePlaceholder = getMessage();
}
}
EDIT
Sorry I forgot this
In Page_Load event of your master page
if(!IsPostBack)
{
messagePlaceholder.InnerHtml = Errors.getMessage();
}

Resources