Retaining enum values in asp.net - c#

I have an asp.net page, wherein i am using enums (with Properties defined in class file in app_code)
Now my problem is whenever page gets postbacks the value of the enum in property gets resetted to the first one
I even tried setting the property as static, but still that didn't helped. below is my enum and property declaration:
private static UrlType _type;
public static UrlType UrlPattern
{
get
{
HttpContext.Current.Response.Write("GET: " +_type + "<br>");
return _type;
}
set
{
_type = value;
HttpContext.Current.Response.Write("SET : " +_type + "<br>");
}
}
public int VanityId { get; set; }
public enum UrlType
{
ArticleOnly,
ArticleCategoryCombination,
Normal,
TechForum
}
and this is how i calls:
public void BindRewrite()
{
GrdRewrite.DataSource = objVanity.GetAllRewriteVanities(Vanity.UrlPattern);
GrdRewrite.DataBind();
if (Vanity.UrlPattern == Vanity.UrlType.ArticleCategoryCombination)
{
GrdRewrite.Columns[2].Visible = false;
GrdRewrite.Columns[3].Visible = GrdRewrite.Columns[5].Visible = GrdRewrite.Columns[6].Visible = true;
}
else if (Vanity.UrlPattern == Vanity.UrlType.ArticleOnly)
{
GrdRewrite.Columns[5].Visible = true;
GrdRewrite.Columns[2].Visible = GrdRewrite.Columns[3].Visible = GrdRewrite.Columns[6].Visible = false;
}
else if (Vanity.UrlPattern == Vanity.UrlType.Normal)
{
GrdRewrite.Columns[2].Visible = true;
GrdRewrite.Columns[3].Visible = GrdRewrite.Columns[5].Visible = GrdRewrite.Columns[6].Visible = false;
}
}
protected void Page_Load(object sender, EventArgs e)
{
pnlAdmin.Visible = (objVanity.UserName == "host");
if (objVanity.UserName == "host")
Enable();
else
FieldsOpenForEditors(objVanity.SiteSupportUrlFormat);
if (!IsPostBack)
{
Vanity.GenerateListFromEnums(drpAdminUrlType);
if (objVanity.UserName == "host")
Vanity.UrlPattern = Vanity.UrlType.ArticleOnly;
else
Vanity.UrlPattern = objVanity.SiteSupportUrlFormat;
BindRewrite();
}
}
can anyone tell me how to retain the value of the enum across postbacks
i think viewstate could be option, but don't have any clue about how to store the enum value and restore the string value casted in enum.

If you want to persist a value between post back, you need to store it in Session, Cache or ViewState.
In your case, ViewState could be a prefer choice.
public UrlType UrlPattern
{
get
{
if (ViewState["UrlPattern"] != null)
return (UrlType)Enum.Parse(typeof(UrlType), ViewState["UrlPattern"].ToString());
return UrlType.Normal; // Default value
}
set
{
ViewState["UrlPattern"] = value;
}
}

Related

Processing multiple values in each other's get property

I am getting a StackOverflow exception on "return TimeOne".
The Timecheck method sets both values depending on their value at any given time. Is there a way to process both values at the outset based on each other?
class Name
{
private string _Timeone
public string TimeOne
{
get
{
return _Timeone
}
set
{
TimeCheck();
_Timeone = value;
}
}
private string _TimeTwo
public string TimeTwo
{
get
{
return _TimeTwo
}
set
{
TimeCheck();
_TimeTwo= value;
}
}
private void TimeCheck()
{
string WrongTime = "....";
if (TimeOne == WrongTime && TimeTwo == WrongTime )
TimeOne = TimeTwo = DateTime.Now.ToString();
else if (TimeOne == WrongTime) TimeOne = TimeTwo
else if TimeTwo == WrongTime) TimeTwo = TimeOne;
}
}
}
The issue is caused by your setters calling TimeCheck, which in turn calls the setters, which calls TimeCheck, ad nauseum.
Break that cycle.
Your TimeCheck function can be rewritten so it sets the backing fields instead of calling the setters:
private void TimeCheck()
{
string WrongTime = "....";
if (_TimeOne == WrongTime && _TimeTwo == WrongTime )
{
_TimeOne = _TimeTwo = DateTime.Now.ToString();
}
else if (_TimeOne == WrongTime)
{
_TimeOne = _TimeTwo;
}
else if (_TimeTwo == WrongTime)
{
_TimeTwo = _TimeOne;
}
}
This breaks the cycle. Your setter can now call TimeCheck without fear of being called back in an endless cycle.
You're getting a stack overflow exception because your setters are calling themselves recursively with no end condition, when you do TimeTwo = value; Instead, you can create a private backing property for each public property and use those in the getters and setters:
private string _timeOne;
private string _timeTwo;
public string TimeOne
{
get { return _timeOne; }
set
{
TimeCheck();
_timeOne = value;
}
}
public string TimeTwo
{
get { return _timeTwo; }
set
{
TimeCheck();
_timeTwo = value;
}
With your current implementation, each time you say TimeOne = value; the setter is being called again, which calls it again, and so on.
EDIT
I agree that TimeCheck() should not be called in the setters. Instead, I think it would be more appropriate to validate those values, and reset them if necessary, elsewhere. Maybe in a service of some sort, or whatever code is setting those properties to begin with.

Passing a true value to a boolean

I am trying to learn C# and I am up to an example that uses a boolean. For the life of me I cant figure out why the program isnt noticing that I am trying to pass a value of true to the boolean. Here is the code in the Form.cs:
namespace WindowsFormsApplication7
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
HappyBirthday birthdayMessage = new HappyBirthday();
string returnedMessage;
birthdayMessage.PresentCount = 5;
birthdayMessage.MyProperty = "Adam";
birthdayMessage.hasParty = true;
returnedMessage = birthdayMessage.MyProperty;
MessageBox.Show(returnedMessage);
}
}
}
Here is the Class that I created:
class HappyBirthday
{
//====================
// CLASS VARIABLES
//====================
private int numberOfPresents;
private string birthdayMessage;
private bool birthdayParty;
//===========================
// DEFAULT CONSTRUCTOR
//===========================
public HappyBirthday()
{
numberOfPresents = 0;
//birthdayParty = false;
}
//===========================
// METHOD
//===========================
private string getMessage(string givenName)
{
string theMessage;
theMessage = "Happy Birthday " + givenName + "\n";
theMessage += "Number of presents = ";
theMessage += numberOfPresents.ToString() + "\n";
if (birthdayParty == true)
{
theMessage += "Hope you enjoy the party!";
}
else
{
theMessage += "No party = sorry!";
}
return theMessage;
}
//================================
// READ AND WRITE PROPERTY
//================================
public string MyProperty
{
get { return birthdayMessage; }
set { birthdayMessage = getMessage(value); }
}
//================================
// WRITE-ONLY PROPERTY
//================================
public int PresentCount
{
set { numberOfPresents = value; }
}
public bool hasParty
{
set { birthdayParty = value; }
}
}
Now I set the initial value to false (even though if my understanding is correct that should be the default value), but when I try to set it = true, the program does not recognize it. Am I supposed to pass a boolean differently then I would a string or int?
You're setting MyProperty before you're setting hasParty. getMessage() is not being called every time MyProperty is polled.
The way MyProperty works is confusing, because the set and get deal with different values (you set the name, and then get the whole message, which is confusing). I'd replace it with a GivenName property and then make the GetMessage() (or expose it as a read-only property Message) public.
Also, you can make your code much simpler by using auto-properties (you can use private gets to keep the write-only behavior, though in the real world write-only properties are very rare, and you should probably just make them public like the sets). And since the default int value is 0, you don't need to specify your default constructor. Here's how the code looks now:
class HappyBirthday
{
public string Message
{
get
{
string theMessage;
theMessage = "Happy Birthday " + GivenName + "\n";
theMessage += "Number of presents = ";
theMessage += PresentCount.ToString() + "\n";
if (HasParty)
{
theMessage += "Hope you enjoy the party!";
}
else
{
theMessage += "No party = sorry!";
}
return theMessage;
}
}
public string GivenName { private get; set; }
public int PresentCount { private get; set; }
public bool HasParty { private get; set; }
}

how to make read only property available in my usercontrol

i make user control from 3 text boxes but i don not how to declare read only property to it i tried many things but it do not work here is my code to make the control
i want to make it read only when needed like if i add checkbox i want if checkbox.check=true make my control readonly
public partial class dateIN : UserControl
{
Dates datess = new Dates();
public dateIN()
{
InitializeComponent();
}
private void dateIN_Leave(object sender, EventArgs e)
{
if (txtDay.Text != "" || txtMonth.Text != "" || txtYear.Text != "")
{
if (!datess.IsHijri(txtDay.Text.Trim() + "/" + txtMonth.Text.Trim() + "/" + txtYear.Text.Trim()))
{
txtDay.Focus();
}
}
}
public string Day
{
set { txtDay.Text = value; }
get { return txtDay.Text; }
}
public string Month
{
set { txtMonth.Text = value; }
get { return txtMonth.Text; }
}
public string Year
{
set { txtYear.Text = value; }
get { return txtYear.Text; }
}
need to know how to make read only property available here plz
just remove the set { } part of the property
Example:
public string Day
{
get { return txtDay.Text; }
}
I dont know the correlation of where your "txtDay", "txtMonth", "txtYear" come from, but you could do something like
public partial class dateIN : UserControl
{
...
...
private bool AllowEditing()
{ return SomeCondition when SHOULD be allowed...; }
public string Day
{
// only allow the set to apply the change if the "AllowEditing" condition
// is true, otherwise, ignore the attempt to assign.
set { if( AllowEditing() )
txtDay.Text = value; }
get { return txtDay.Text; }
}
// same concept for month and year too
}
so may you add some flag to your set when it is true then you set a value.
also you can work with textbox property called ReadOnly.

Unable to edit values in a DataGridView (using BindingList)

It seems that, due to an unknown cause, I am now unable to edit anything in my DataGridView. The DGV's ReadOnly property value is false, and all columns except for one all have the ReadOnly property set to false as well.
I'm beginning to think that it may be due to a special value I tried adding to one of my classes, one that I only wanted to be modified within the class, but still read only to the public. I don't think that value is messing with anything else, but none the less, here is the relevant portion of my code:
private void loaderWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
loadingBar.Value = e.ProgressPercentage;
if (e.UserState != null)
{
savefiles.Add((SaveFile)e.UserState);
}
}
Where savefiles is a BindingList, and where SaveFile is my class:
public class SaveFile
{
private string d_directory;
private int d_weirdnumber;
private bool d_isautosave;
private string d_fullname;
private string d_datatype;
private string d_owner;
private bool d_isquicksave;
private string d_title;
private string d_gametime;
public SaveFile() { }
public SaveFile(string directory, int weirdnumber, bool isautosave, string fullname, string datatype, string owner, bool isquicksave, string title)
{
d_directory = directory;
d_weirdnumber = weirdnumber;
d_isautosave = isautosave;
d_fullname = fullname;
d_datatype = datatype;
d_owner = owner;
d_isquicksave = isquicksave;
d_title = title;
}
public string Gametime
{
get { return d_gametime; }
}
public string Datatype
{
get { return d_datatype; }
set { d_datatype = value; }
}
public string Title
{
get { return d_title; }
set { d_title = value; }
}
public bool IsQuickSave
{
get { return d_isquicksave; }
set { d_isquicksave = value; }
}
public bool IsAutoSave
{
get { return d_isautosave; }
set { d_isautosave = value; }
}
public string Directory
{
get { return d_directory; }
set { d_directory = value; }
}
public string FullName
{
get { return d_fullname; }
set
{
d_fullname = value;
string[] split = value.Split(new char[]{'-'});
foreach (string str in split)
{
if (System.Text.RegularExpressions.Regex.IsMatch(str, "^\\d\\d:\\d\\d:\\d\\d$"))
{
d_gametime = str;
}
}
}
}
public int Weirdnumber
{
get { return d_weirdnumber; }
set { d_weirdnumber = value; }
}
public string Owner
{
get { return d_owner; }
set { d_owner = value; }
}
}
Gametime is that special property I mentioned earlier. It doesn't have a set function, but according to this, I should be in the clear, right?
Can anyone then tell me why I may not be able to edit any of the DGV cells?
EDIT: I just found out that not setting AutoGenerateColumns to false allows me to edit again, but I still don't know why.
After several hours, a friend finally took a look at it over Remote Desktop. He wrote a function to force all columns to have a non read-only status, and go figure, it worked. So we looked at the column properties in the editor, and somehow... I don't know why... they were all set to Read only. I swear I checked them 4 times before.
The lesson of this story (I guess): When in doubt, check your settings. When not in doubt, become doubtful. Otherwise, file a bug report to Microsoft :\

Problem with Efficient Gridview paging without datasource control

I am trying to do efficient paging with a gridview without using a datasource control. By efficient, I mean I only retrieve the records that I intend to show.
I am trying to use the PagerTemplate to build my pager functionality.
In short, the problem is that if I bind only the records that I intend to show on the current page, the gridview doesn't render its pager template, so I don't get the paging controls.
It's almost as if I MUST bind more records than I intend to show on a given page, which is not something I want to do.
You need to create a custom gridview control that inherits from GridView. Without the DataSourceControl, the gridview does not have knowledge of the total number of records that could potentially be bound to the control. If you bind 10 out of 100 records and you set the PageSize property to 10, the gridview only knows that there are 10 records which will be less than or equal to the PageSize and the pager control will not display. In order for your gridview to show the pager, it has to know the total number of records that could potentially be retrieved. By inheriting the gridview and overriding the InitializePager method, we can intercept the pagedDataSource and modify the AllowCustomPaging and VirtualCount methods.
This is the one I created
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace cly.Web.CustomControls
{
public class clyGridView : GridView
{
private const string _virtualCountItem = "bg_vitemCount";
private const string _sortColumn = "bg_sortColumn";
private const string _sortDirection = "bg_sortDirection";
private const string _currentPageIndex = "bg_pageIndex";
public clyGridView ()
: base()
{
}
#region Custom Properties
[Browsable(true), Category("NewDynamic")]
[Description("Set the virtual item count for this grid")]
public int VirtualItemCount
{
get
{
if (ViewState[_virtualCountItem] == null)
ViewState[_virtualCountItem] = -1;
return Convert.ToInt32(ViewState[_virtualCountItem]);
}
set
{
ViewState[_virtualCountItem] = value;
}
}
public string GridViewSortColumn
{
get
{
if (ViewState[_sortColumn] == null)
ViewState[_sortColumn] = string.Empty;
return ViewState[_sortColumn].ToString();
}
set
{
if (ViewState[_sortColumn] == null || !ViewState[_sortColumn].Equals(value))
GridViewSortDirection = SortDirection.Ascending;
ViewState[_sortColumn] = value;
}
}
public SortDirection GridViewSortDirection
{
get
{
if (ViewState[_sortDirection] == null)
ViewState[_sortDirection] = SortDirection.Ascending;
return (SortDirection)ViewState[_sortDirection];
}
set
{
ViewState[_sortDirection] = value;
}
}
private int CurrentPageIndex
{
get
{
if (ViewState[_currentPageIndex] == null)
ViewState[_currentPageIndex] = 0;
return Convert.ToInt32(ViewState[_currentPageIndex]);
}
set
{
ViewState[_currentPageIndex] = value;
}
}
private bool CustomPaging
{
get { return (VirtualItemCount != -1); }
}
#endregion
#region Overriding the parent methods
public override object DataSource
{
get
{
return base.DataSource;
}
set
{
base.DataSource = value;
// store the page index so we don't lose it in the databind event
CurrentPageIndex = PageIndex;
}
}
protected override void OnSorting(GridViewSortEventArgs e)
{
//Store the direction to find out if next sort should be asc or desc
SortDirection direction = SortDirection.Ascending;
if (ViewState[_sortColumn] != null && (SortDirection)ViewState[_sortDirection] == SortDirection.Ascending)
{
direction = SortDirection.Descending;
}
GridViewSortDirection = direction;
GridViewSortColumn = e.SortExpression;
base.OnSorting(e);
}
protected override void InitializePager(GridViewRow row, int columnSpan, PagedDataSource pagedDataSource)
{
// This method is called to initialise the pager on the grid. We intercepted this and override
// the values of pagedDataSource to achieve the custom paging using the default pager supplied
if (CustomPaging)
{
pagedDataSource.VirtualCount = VirtualItemCount;
pagedDataSource.CurrentPageIndex = CurrentPageIndex;
}
base.InitializePager(row, columnSpan, pagedDataSource);
}
protected override object SaveViewState()
{
//object[] state = new object[3];
//state[0] = base.SaveViewState();
//state[1] = this.dirtyRows;
//state[2] = this.newRows;
//return state;
return base.SaveViewState();
}
protected override void LoadViewState(object savedState)
{
//object[] state = null;
//if (savedState != null)
//{
// state = (object[])savedState;
// base.LoadViewState(state[0]);
// this.dirtyRows = (List<int>)state[1];
// this.newRows = (List<int>)state[2];
//}
base.LoadViewState(savedState);
}
#endregion
public override string[] DataKeyNames
{
get
{
return base.DataKeyNames;
}
set
{
base.DataKeyNames = value;
}
}
public override DataKeyArray DataKeys
{
get
{
return base.DataKeys;
}
}
public override DataKey SelectedDataKey
{
get
{
return base.SelectedDataKey;
}
}
}
}
Then when you are binding the data:
gv.DataSource = yourListOrWhatever
gv.VirtualItemCount = numOfTotalRecords;
gv.DataBind();

Categories