State of checkbox lost after postback in a custom template field - asp.net

I have created a custom checkbox template field by deriving it from System.Web.UI.WebControls.TemplateField. The template for this field has been created by creating a class which implements ITemplate interface. When any postback happens on the page the values in the checkboxes is lost.
To get this working temporarily I have used viewstate to store the state of checkboxes in the checkbox column, but going further I want to completely avoid this as I will be using more template fields in same fashion in my application.
Please let me know if I am missing anything.
Following is the code:
namespace MyControls
{
public class CheckBoxTemplateField : TemplateField
{
public CheckBoxTemplateField()
{
this.HeaderTemplate = new CheckBoxTemplate();
this.ItemTemplate = new CheckBoxTemplate();
}
}
public class CheckBoxTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
CheckBox chk = new CheckBox();
container.Controls.Add(chk);
}
}
}
Regards,
Gaurav

checkbox is known with their problem maintaining their value in postback
1 solution is to store its value in hidden fiesld and to read it in server.
p.s. thhis has nothing to do with viewstate.input control doesnt saves their value in viewstate ( excpet textbox which has the 'ontextchange' event)

Related

Enable/Disable FINISH button of wizard based on user input

I have created a wizard in AX 2012 using wizard wizard... Now i need to put 1 functionality i.e., to Enable or Disable FINISH button based on user input.
I have already tried these 3 ways but without success..
this.finishenabled() -- on SetupNavigation method of wizard class
finishenabled[formrun.tabidx()] = false -- on SetupNavigation method of wizard class
syswizard.finishenable(false, curtabidx(),false) - on Tabpage of wizard form
please do reply if anyone have a solution for this....
The Wizard class has a validate method in which you will do the following:
boolean validate()
{
if(SomeTestCondition)
{
return true;
}
return false;
}
According to Microsoft, this method does the following:
Used to validate user input, and called before the wizard is closed.
It returns false if user input is invalid. This will prevent the run method from being called when the user clicks the Finish button.
Wizard Class on MSDN
Additionally, you can use the textchanged() method on the field you want to validate (or if not text, you can use the changed method of the object).
if (this.text())
{
if (!sysWizard.isNextEnabled())
{
sysWizard.nextEnabled(true, sysWizard.curTab(), false);
}
}
else
{
if (sysWizard.isNextEnabled())
sysWizard.nextEnabled(false, sysWizard.curTab(), false);
}
Also from MSDN Enable Buttons
In SysWizard class the check to enable / disable the finishButton is inside a check for this.hasFinishButton() (see SysWizard.enableButtons).
I overcame this issue by overwriting the hasFinishButton() method on your wizard class and set the ret = true. This does mean however that your finish buttons will show in all steps, but you can hide this with other code if necessary.
The simplest way to enable/disable the Finish button on a Wizard form called from a SysWizard class is to retrieve the FormControl object from the FormRun object using the FormControlId and then set the Enabled property based on the your test condition, such as whether another FormControl contains a value. There are many ways to implement this. I'll provide two examples.
In the first example, all of the modifications are done on the Wizard Form.
A FormControl is used that can be called like any FormControl that has the AutoDeclaration property set to Yes.
In the second example, I'll override the finishEnabled() method on my Wizard class, so it behaves in the manner that was expected.
In each example, the formControl is found using the FormControlId which takes the control's label text ("Finish") as the argument. I found the correct Label ID by doing a "Lookup Label/Text" on "Finish" in the code editor and then selected the SYS label with "Label for Finish button in wizard" in the label's Description.
Example 1: FormControl object on Wizard Form:
In the Form classDeclaration add the following:
class FormRun extends ObjectRun
{
//FormControl objects used to get SysWizard Finish Button
FormControlId finishButtonId;
FormControl finishButton;
}
Initialize the new FormControl in the top level Form init() method:
void init()
{
super();
if (element.Args().caller())
{
sysWizard = element.Args().caller();
}
finishButtonId = sysWizard.formRun().controlId("#SYS302811");
finishButton = sysWizard.formRun().control(finishButtonId);
finishButton.enabled(false);
}
Now you can use the control like you would any other form control. In this case, I'm using the state of checkbox control named IsFinished in my WizardForm as the test condition and updating the FormControl state from the IsFinished.clicked() method:
public void clicked()
{
super();
//set FormControl state based on the current value of the checkbox
finishButton.enabled(this.checked());
}
*Example 2:*Override the finishEnabled() method in your Wizard class:
Note that you'll need to set the default values for the method parameters otherwise AX will throw a compile error because it doesn't match the signature from the base class. For some reason, AX doesn't properly create the method signature. Get rid of the default call to super and replace it with the code below:
public boolean finishEnabled(boolean _enabled = false,
int _idx = this.curTab(),
boolean _setfocus = false)
{
return this.formRun().control(this.formRun().controlId("#SYS302811")).enabled(_enabled);
}
Initialize the control value in the Form init() method:
void init()
{
super();
if (element.Args().caller())
{
sysWizard = element.Args().caller();
}
sysWizard.finishEnabled();
}
Call the class method when your controls are updated:
public void clicked()
{
super();
//set FormControl state based on the current value of the checkbox
sysWizard.finishEnabled(this.checked());
}

How two read one user control label text in another use control?

I am using two user controls in my web application. I want to read a Label text from a user control via another user control. How can i read it?
You should refactor your code and not rely to content of some label on another UI control. Get that value the same way as you do in that User Control, or extract that functionality in another class to avoid code duplication, and call it from both places.
But, if you wont to stick with this existing code you should create Interface and capture all UserControls functionality that you wont to called from outside code (in your case : return label text). Then implement that interface in User Controls that must be called from outside, after that is all about finding control instances, you can do that by enumerating all Page child controls. Here is the example code of simple interface that defines that control must return some Label text, and a class that finds user control by name in control tree :
public interface IUserControl
{
string LabelText();
}
public class PageUserControls
{
private Page parentPage;
public PageUserControls(Page myParentPage)
{
this.parentPage = myParentPage;
}
private IEnumerable<Control> EnumerateControlsRecursive(Control parent)
{
foreach (Control child in parent.Controls)
{
yield return child;
foreach (Control descendant in EnumerateControlsRecursive(child))
yield return descendant;
}
}
public IUserControl GetControl(string controlName)
{
foreach (Control cnt in EnumerateControlsRecursive(this.parentPage))
{
if (cnt is IUserControl && (cnt as UserControl).AppRelativeVirtualPath.Contains(controlName))
return cnt as IUserControl;
}
return null;
}
}
then you have to implement that interface in user control that holds that Label :
public partial class WebUserControl1 : System.Web.UI.UserControl, IUserControl
{
public string LabelText()
{
return Label1.Text;
}
}
And finally use it from another User control :
PageUserControls puc = new PageUserControls(this.Page);
string txt1 = puc.GetControl("WebUserControl1.ascx").LabelText();
btw. method EnumerateControlsRecursive is adopted from SO answer to Finding all controls in an ASP.NET Panel?
use like this...
create one public property in the user control and call that property using user controls name where you want that value....
Take a look at this article on MSDN.
In a short, you can access other controls if you know the ID.

Extending DropDownList to include an extra option

I want to extend DropDownList control to include an option for creating or editing the options. For example; for a list of projects in the dropdown list, there will be another option that says "Create new project..." or "Edit projects..." and this will be the last option in the list. When user selects this option, the selectedIndex or selectedItem will not change and corresponding action will be taken (for example a popup window shows up). This will be a convenient way for the end user.
Now I want this to work independent of the context and the class must be reusable. User will only specify the optionText and optionFunction to work this out. The basic structure of the class looks like this:
public class OptiveDropDownList extends DropDownList
{
private var _enableOption:Boolean;
private var _optionText:String;
private var _originalDataProvider:IList;
[Bindable] public var optionFunction:Function;
public function OptiveDropDownList()
{
super();
}
public function set optionText(value:String):void
{
_optionText = value;
dataProvider = _originalDataProvider;
}
public function set enableOption(value:Boolean):void
{
_enableOption = value;
dataProvider = _originalDataProvider;
}
public override function set dataProvider(value:IList):void
{
_originalDataProvider = value;
var dp:IList = null;
if(!value){
dp=new ArrayCollection(value.toArray());
if(_enableOption){
var opt:Object=new Object();
opt[labelField]=_optionText;
dp.addItem(opt);
}
}
super.dataProvider = dp;
}
[Bindable]
public override function get dataProvider():IList
{
return _originalDataProvider;
}
}
I hope my code is clear to understand, I am adding an extra object to the dataprovider for the option. Field names are self-explanatory.
Now my question is how to know whether the dataprovider's items have changed? Which functions should I override and how to do it. I have tried using a ChangeWatcher to watch the length property of the dataprovider, but it doesnt work if only an object in the dataprovider has changed. I need to capture these changes and update the view.
I also need to capture the selection and call optionFunction, preventing the default action not to give index out of bounds error.
Thanks in advance.
Just add an event listener to the original dataProvider. All implementations of IList should dispatch CollectionEvent.COLLECTION_CHANGE when the the list changes (e.g. add, remove or when an existing object in the list has been changed). In your event handler you can update the DropDownList's dataProvider accordingly.
By overriding the mx_internal method setSelectedIndex() you can adjust the selection according to your wishes. Take a look at the blog post "Disable selection on some items in a spark List" for some inspiration.

ITemplate, the reason for leaving InstantiateIn(Control container)

I'm implementing the ITemplate interface in ListView control. If i realize it for ItemTemplate in my custom class, everything will be OK. I mean, the runtime will invoke InstantiateIn when i use
ListView.ItemTemplate = new CustomClass();
CustomClass :ITemplate
{
public void InstantiateIn(Control container)
{
HtmlTable table = CreateHeader();
container.Controls.Add(table);
}
...
}
But i want to do the same with ListView.LayoutTemplate. In this case, the runtime invokes InstantiateIn only one time, but every next update it leaves my method. What is the reason for it?
Layout template says how the root container does look like, it is not per item thing.
I have to change my LayoutTemplate after clicking different buttons.
And My LayoutTemplate has a header for the whole ListView. I have to change it, it depends on button.
Also i have two custom classes with implementations of ITemplate (one for ItemTemplate and one for LayoutTemplate). I am going to realise the folowing behaviour:
1). If i click Button1
ListView.ItemTemplate = new CustomItemClass1();
ListView.LayoutTemplate = new CustomLayuotClass1();
2). If i click Button2
ListView.ItemTemplate = new CustomItemClass2();
ListView.LayoutTemplate = new CustomLayuotClass2();
But i can't see my header of LayoutTemplate more, then one time.

How to get design surface rendering and design time datasource selection with an asp.net user control

If I create a user control (EDIT:not a web control/server control) it's pretty trivial to get databinding. I just add a datasourceID property.
In code behind (vb)
Partial Public Class BandedControl
Inherits UserControl
Public Property DataSourceID() As String
Get
Return MyGridView.DataSourceID
End Get
Set(ByVal value As String)
MyGridView.DataSourceID = value
End Set
End Property
End Class
In code behind (c#)
public partial class BandedControl : UserControl
{
public string DataSourceID {
get { return MyGridView.DataSourceID; }
set { MyGridView.DataSourceID = value; }
}
}
My issue is that this breaks design time rendering and also I don't get a drop down list to choose my datasource. How do I resolve this. (Hint: I think I need a type convertor, but all the info I can find relates to server controls not user controls).
You could try adding the IDReferenceProperty attribute to your property definition...
public partial class BandedControl : UserControl
{
[System.Web.UI.IDReferenceProperty(typeof(DataSourceControl))]
public string DataSourceID
{
get
{
return MyGridView.DataSourceID;
}
set
{
MyGridView.DataSourceID = value;
}
}
}
See http://msdn.microsoft.com/en-us/library/system.web.ui.idreferencepropertyattribute.aspx for more info about the IDReferencePropertyAttribute class.
If that doesn't work - I'd also try to inherit from DataBoundControl instead of UserControl and see if that gets you anywhere.
Web UserControls are compiled dynamically at run time and so are not rendered at Design time, what you want to do is create a Web Custom Control. Your best bet here is to extend one of the existing Bindable Web Controls
http://msdn.microsoft.com/en-us/library/aa651710(VS.71).aspx
Not sure if this is exactly what you want but I seem to remember them showing something similar to this in some dnr tv episodes.
I think it was Miguel Castro episodes 1 & 2, but it could be episode 31.
An archive of all the videos is here

Resources