In a custom control I put the property
[Bindable(true), Category("Appearance"), DefaultValue(""), Localizable(true), Description("")]
public string InitValue
{
get { return ViewState["InitValue"].ToString(); }
set { ViewState["InitValue"] = value; }
}
When I include it on a page and run the page I receive the Object reference not set... exception. It shoes a line number which is the get above.
It happens when I don't set the property, though I don't want the property to be required.
Is it considered a good option to use
get { return ViewState["InitValue"]==null ? "" : ViewState["InitValue"].ToString(); }
or better to make property into object and ToString() it when needed?
Should check the value exist before returning it
public string InitValue
{
get
{
if(ViewState["InitValue"] != null)
return ViewState["InitValue"].ToString();
return "default value here";
}
set { ViewState["InitValue"] = value; }
}
The way I have always handled this is:
public string InitValue
{
get
{
if(ViewState["InitValue"] == null)
ViewState["InitValue"] = [DEFAULT VALUE];
return ViewState["InitValue"].ToString();
}
set { ViewState["InitValue"] = value; }
}
Your get is doing a ToString() on a nullable property. Handle it and you'll be just fine. In the following code, I have assumed "" as the default value.
get { (return ViewState["InitValue"] ?? string.Empty).ToString(); }
Related
I have a group of 7 checkboxes in checkboxlist user control. I build a string in the selectedIndexchanged event for the boxes checked, pass to ViewState and then pass ViewState to the Property. I do this because in the instance when no checkboxes are selected I want to handle null. The problem is no matter how I check for null, the system is throwing object reference error. This current setup works fine if at least one checkbox is checked but if none are checked it fails. How do I check for null? Should I be checking for null in the property or the host aspx page?
I have researched difference ways to do this and I have tried many. My thought is using IsNullOrEmpty or IsNullOrWhiteSpace would be the correct way to go but neither are working.
User Control class - global variable
private string _daysOffInputString = string.Empty;
User Control Property
public string DaysOffSelectedValues
{
get
{
if (string.IsNullOrEmpty(ViewState["DaysOff"].ToString()))
{
_daysOffInputString = string.Empty;
}
else
{
_daysOffInputString = ViewState["DaysOff"].ToString();
}
return _daysOffInputString;
}
set { _daysOffInputString = value; }
User Control event
protected void CbDaysOff_SelectedIndexChanged(object sender, EventArgs e)
{
CheckBoxList chkbx = (CheckBoxList)sender;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chkbx.Items.Count; i++)
{
if (chkbx.Items[i].Selected)
{
sb.Append(chkbx.Items[i].Text + ", ");
}
if (!String.IsNullOrEmpty(sb.ToString()))
{
//Remove last comma & space from string
_daysOffInputString = sb.ToString().Substring(0, sb.ToString().Length - 2);
}
else
{
_daysOffInputString = string.Empty;
}
}
ViewState["DaysOff"] = _daysOffInputString;
}
aspx page - snippet where I retrieve uc property value:
case 2:
blnFlag = false;
ucDaysOff uc3 = row.Cells[3].FindControl("ucDaysOff3") as ucDaysOff;
strAnswer = uc3.DaysOffSelectedValues; //e.g. "Sat, Sun"
break;
SOLUTION: In the user control property DaysOffSelectedValues I was casting ViewState["DaysOff"] to string before checking for null which was the problem. Here's the code that works:
public string DaysOffSelectedValues
{
get
{
if (ViewState["DaysOff"] == null)
{
//_daysOffInputString = string.Empty; }
_daysOffInputString = "Nothing to see here.";
}
else
{
_daysOffInputString = ViewState["DaysOff"].ToString();
}
return _daysOffInputString;
}
set { _daysOffInputString = value; }
}
You should always check if the object, in this case ViewState, is null before using it. Lets say ViewState["DaysOff"] has not been created or has been removed.
Then this will throw a nullreference:
string str = String.IsNullOrEmpty(ViewState["DaysOff"].ToString());
Because you are not checking the ViewState object for null, but the string it is supposed to hold.
So do this
if (ViewState["DaysOff"] != null)
{
string str = ViewState["DaysOff"].ToString();
}
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.
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.
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;
}
I am in need of some help. I am building a custom web user control which is going to be picking colours.
As of right now, it has two [asp:textbox]es on the page (foregroundColour and backgroundColour).
I want my foreground colour to default to "FFFFFF" and my background colour to default to "000000", AND I the user to be able to specify their own initial values though the tag.
<ucFontChooser id="testchooser" runat="server" foregroundcolor="AABBCC" />
I have two properties that are tied to the textboxes:
[DefaultValue("000000")]
public string ForegroundColor { get { return foregroundColorSelectorHex.Text; } set { foregroundColorSelectorHex.Text = value; } }
[DefaultValue("FFFFFF")]
public string BackgroundColor { get { return backgroundColorSelectorHex.Text; } set { backgroundColorSelectorHex.Text = value; } }
Please note that I am aware that the DefaultValue is only for the visual studio property window and doesn't actually set any value.
However, I have tried to set the default value by in the constructor of the usercontrol to do:
ForegroundColor = "000000"
This gives me an exception, because at the point of the constructor, the foregroundColorSelectorHex is null.
So if I try and setting the default in the OnInit event, or on *Page_Load* then it simply always uses the default I set and the set property value of "AABBCC" is overwritten.
What is the correct way to do what am I trying?
Thank you.
After much debugging, I came up with a solution to do exactly what I need.
public override string ID
{
set
{
base.ID = value;
InitializeProperties();
}
}
protected void InitializeProperties()
{
ForegroundColor = "000000";
BackgroundColor = "ffffff";
EnableBackgroundColor = false;
PrimaryFont = "Arial";
SecondaryFont = "Helvetica";
TertiaryFont = "sans-serif";
}
the .NET framework will call mycontrol.ID = "bla", which is when the user controls subcontrols come into context. It is called BEFORE the containing control/page reads the tags attributes and sets the properties.
Looks hacky, but works great.
I think a complete answer would be too long to answer here, and it's documented at MSDN already.
See this page: http://msdn.microsoft.com/en-us/library/ms972975.aspx
And search for the text "Adding Properties and Methods to a User Control"
(But read the whole article anyway so you understand the details.)
However, from the code in the article, it should you how to return a default value if the property is null. Assuming you have a property named CategoryID, the property should be defined as:
public int CategoryID
{
get
{
object o = ViewState["CategoryID"];
if (o == null)
return 0; // return a default value
else
return (int) o;
}
set
{
ViewState["CategoryID"] = value;
}
}
You can use the same pattern to define the color.
Try keeping the value of the property in the viewstate and then setting the .Text in the Page_PreRender, like so:
public string ForegroundColor
{
get
{
if (ViewState["forecolor"] == null)
{
ViewState["forecolor"] = "000000";
}
return (string) ViewState["forecolor"];
}
set
{
ViewState["forecolor"] = value;
}
}
protected override void OnInit(EventArgs e)
{
this.PreRender += Page_PreRender;
base.OnInit(e);
}
private void Page_PreRender(object sender, EventArgs e)
{
foregroundColorSelectorHex.Text = ForegroundColor;
}
Not sure this will work, but could you do something like this in your page_load:
protected void Page_Load {
if (String.IsNullOrEmpty(ForegroundColor))
ForegroundColor = "FFFFFF";
}
You should initialize the value when it is not postback i.e.
if(!Page.IsPostBack){
//Initialize your values
ForegroundColor = "FFFFFF";
}
Can't you create your foregroundColorSelectorHex and backgroundColorSelectorHex in the constructor ?
public string ForegroundColor {
get { return foregroundColorSelectorHex.Text; }
set { foregroundColorSelectorHex.Text = value; }
}
public string BackgroundColor {
get { return backgroundColorSelectorHex.Text; }
set { backgroundColorSelectorHex.Text = value; }
}
public FontChooser () {
foregroundColorSelectorHex = new ColorSelector();
backgroundColorSelectorHex = new ColorSelector();
ForegroundColor = "FFFFFF";
BackgroundColor = "000000";
}