How to declare var as global which stores value of controls? - c#

I have two radio buttons in CriminalityInformationFormViewDisposal and I'm finding this controls dynamically as follows
var siaHasConvictions =
((RadioButtonList)CriminalityInformationFormViewDisposal.FindControl(ContactEntity.SIA_HASCOVICTIONS));
var siaHasOffencesAwatingTrial =
((RadioButtonList)CriminalityInformationFormViewTrial.FindControl(ContactEntity.SIA_HASOFFENCEAWAITINGTRIAL));
now on one page whenever I need to fetch the value of radio buttons i.e. whether it is selected or not every time I need to define var to find control first and then I check for its value...now it increases code line ..is there any way so I can make this findcontrol part global for that one page and then I access its value like we do for normal control ,please help me out for this,as I tried it to declare before page load,,,but gives error for gridcontrol

There is no easy way in my opinion, but this might help you not repeat the code over and over again:
private RadioButtonList SiaHasConvictions
{
get
{
return (RadioButtonList)CriminalityInformationFormViewDisposal.FindControl(ContactEntity.SIA_HASCOVICTIONS);
}
}
With this property, you can just use this.SiaHasConvictions in your code. You could optimize this by saving the reference once in a variable:
private RadioButtonList _siaHasConvictions;
private RadioButtonList SiaHasConvictions
{
get
{
if (this._siaHasConvictions == null)
{
this._siaHasConvictions = (RadioButtonList)CriminalityInformationFormViewDisposal.FindControl(ContactEntity.SIA_HASCOVICTIONS);
}
return this._siaHasConvictions;
}
}

Using the second piece of #Patrick Hofman's code is NOT guaranteed a correct behavior. If the FindControl method may return different values each time you call it, this implementation will go wrong since _siaHasConvictions won't get changed anymore once set.
However, I was inspired from #Patrick Hofman's idea of using property, you could use ?? operator in your Property to make things even easier:
private RadioButtonList _siaHasConvictions;
private RadioButtonList SiaHasConvictions
{
get { return this._siaHasConvictions ?? (this._siaHasConvictions = (RadioButtonList)CriminalityInformationFormViewDisposal.FindControl(ContactEntity.SIA_HASCOVICTIONS)); }
}
Here is the explanation and some examples of using ?? operator, and in short:
The ?? operator is called the null-coalescing operator. It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.

Related

Find textbox by name in a list of textboxes

Given a list of RichTextBox, I would like to access one by its name.
So for example:
EDIT
I shouldn't have used the loop in the question. I am trying to access the name without a for loop.
public RichTextBox boxFinder(List<RichTextBox> boxes)
{
return boxes.Find("boxname")
}
The simplest method would be to use FirstOrDefalut
return boxes.FirstOrDefault(b => b.Name == "MyName");
First will throw if there is no matching element. Note that this essentially performs a foreach that breaks after an element is found under the hood.
Find is a function which takes a predicate (that is, a delegate which returns a bool). You can call find using lambda:
public RichTextBox boxFinder(List<RichTextBox> boxes)
{
return boxes.Find(box=>box.Name == "boxname");
}
Of course wrapping it in a function like this probably doesn't buy you much.

Handling Nullable Properties when posting to a ComboBox DropDownList

I have a custom class Diary, which has a nullable property DeadlineType
On one of my Forms I have a ComboBox in DropDownList mode, which is populated with all the possible values that DeadlineType can take. When a Diary is selected, the form is populated with all the properties, but I have an issue with the DeadlineType property in that, when it is null, it requires more code than I believe it should i.e.
if (amendDiary.DeadlineType != null)
{
cboDeadlineType.Text = amendDiary.DeadlineType.ToString();
}
else
{
cboDeadlineType.Text = null;
}
I am sure there must be a more concise way to achieve this, or certainly hope so, because this scenario is repeated a lot throughout my application i.e. posting nulls to ComboBoxes.
I did try
cboDeadlineType.Text = amendDiary.DeadlineType.ToString() ?? null
But that gives an 'Object not set to an instance' error.
Try this:
cboDeadlineType.Text = (amendDiary.DeadlineType ?? "").ToString();
Note that setting the ComboBox.Text to null means the same as setting it to "" (The combo Text is empty in both cases).
Another solution is use the Convert.ToString method:
cboDeadlineType.Text = Convert.ToString(amendDiary.DeadlineType);
With that solution, if the input is null, the cboDeadlineType.Text is assigned exactly to null.
try
cboDeadlineType.Text = amendDiary.DeadlineType!=null ?amendDiary.ToString() :"";

Searching for pages with any value in property

EPiServer only:
How do I search for pages with any value in a given property? I can do a search for pages with a specific value in the property, but I can't figure out how to search for "not empty".
For example, this doesn't work:
var criterias = newPropertyCriteriaCollection
{
new PropertyCriteria()
{
Condition = CompareCondition.NotEqual,
Name = "MyProperty",
IsNull = false,
Type = PropertyDataType.String,
Value = ""
}
};
var pages = DataFactory.Instance.FindPagesWithCriteria(PageReference.StartPage, criterias);
An exception is thrown, "The crieria value cannot be null or empty. Set the IsNull property to search for null."
Any ideas?
Yeah, this is confusing. In case anyone else stumbles on this, here's how to search for pages with a certain PageReference property set to something:
new PropertyCriteria()
{
createdCriteria.Name = "MyProperty";
createdCriteria.Type = PropertyDataType.PageReference;
createdCriteria.Condition = EPiServer.Filters.CompareCondition.NotEqual;
createdCriteria.Value = "0";
createdCriteria.IsNull = false;
}
Unless I'm missing a trick, this doesn't appear to be possible using the EPiServer PropertyCriteriaCollection.
I've had a dig around in reflector and here are my findings. The FPWC method eventually calls EPiServer.DataAccess.PropertySearchDB.FastFindPagesWithCriteria().
Within this method is the following:
foreach (PropertyCriteria criteria in criterias)
{
if (criteria.IsNull)
{
criteria.Value = null;
}
else if (string.IsNullOrEmpty(criteria.Value))
{
throw new EPiServerException("The crieria value cannot be null or empty. Set the IsNull property to search for null.");
}
...
}
So its not possible to search for an empty string value, without setting IsNull to true. This is then fed down to the EPiServer.DataAccess.PropertySearchDB.ExecuteCriteria method, which constructs and formats the DB command. Because IsNull is true, the netPropertySearchNull stored proc is used. Searching for a string needs to use the netPropertySearchString stored proc.
if (criteria.IsNull && !PageDB.IsMetaData(criteria.Name))
{
cmd.CommandText = "netPropertySearchNull";
}
My suggestion would be to load the full list of pages and filter using linq. Alternatively you could look into bypassing the API and implementing a direct DB query, or use some of the low level EPiServer data access methods (not recommended)
Apologies for my first answer - I really should test code before posting :)
I've seen something where the page has a a hidden bool property "Property X contains a value" that is set in the Saving event.
Then that bool property is used as a PropertyCriteria instead of the one you are REALLY interested in.
To find empty values you need to specify the IsNull property on the PropertyCriteria and use the Equal compare condition.
E.g
var criterias = newPropertyCriteriaCollection
{
new PropertyCriteria()
{
Condition = CompareCondition.NotEqual,
Name = "MyProperty",
IsNull = true,
Type = PropertyDataType.String
}
};

Using "as" and expecting a null return

For example. Lets say we have a stackpanel on a form. Its full of both Grids and Labels. I want to loop through all the Grids and do some operation on them but leave the Lables intact. At the moment I am doing it this way.
foreach(UIElement element in m_stacker.Children)
{
Grid block = element as Grid;
if(block != null)
{
//apply changes here
}
}
So i'm using the fact that "as" returns null if it cannot cast into the required type. Is this an ok thing to do or is there a better solution to this problem?
What about OfType()?
foreach( var grid in m_stacker.Children.OfType<Grid>() ) { ... }
This will loop only over the children of type Grid, so no need to cast or check the type at all.
Yes, it's the right way to do it (considering "applying changes" will need to use the cast result).
However, if you are not going to use the cast return value, you can simply use is.
Using is and then casting again with the cast operator (parenthesis) is frowned upon.
It will work fine. What you can do is however just use "is".
foreach(UIElement element in m_stacker.Children)
{
if(element is Grid)
{
//apply changes here
}
}
If you are going to use block as a Grid then this is exactly the right way to code it.
Checking using is (to my mind) produces less readable code as illustrated in the following two bad examples:
if (element is Grid)
{
Grid block = element as Grid;
// Do stuff
}
if (element is Grid)
{
Grid block = (Grid)element;
// Do stuff
}
Don't do either of these.
You're saying if element is a grid then cast it.

Refactor help c#

I have several hundred lines of code like this:
if (c.SomeValue == null || c.SomeProperty.Status != 'Y')
{
btnRecordCall.Enabled = false;
}
if (c.SomeValue == null || (c.SomeProperty.Status != 'Y' &&
c.SomeOtherPropertyAction != 'Y'))
{
btnAddAction.Enabled = false;
}
if (c.SomeValue == null || c.SomeProperty.Processing != 'Y')
{
btnProcesss.Enabled = false;
}
How can I refactor this correctly? I see that the check 'c.SomeValue == null' is being called every time, but it is included with other criteria. How can I possibly eliminate this duplicate code?
I would use the specification pattern, and build composite specifications that map to a proper Enabled value.
The overall question you want to answer is whether some object c satisfies a given condition, which then allows you to decide if you want something enabled. So then you have this interface:
interface ICriteria<T>
{
bool IsSatisfiedBy(T c);
}
Then your code will look like this:
ICriteria<SomeClass> cr = GetCriteria();
btnAddAction.Enabled = cr.IsSatisfiedBy(c);
The next step is to compose a suitable ICriteria object. You can have another ICriteria implementation, (in additon to Or and And), called PredicateCriteria which looks like this:
class PredicateCriteria<T> : ICriteria<T>
{
public PredicateCriteria(Func<T, bool> p) {
this.predicate = p;
}
readonly Func<T, bool> predicate;
public bool IsSatisfiedBy(T item) {
return this.predicate(item);
}
}
One instance of this would be:
var c = new PredicateCriteria<SomeClass>(c => c.SomeValue != null);
The rest would be composition of this with other criteria.
If you don't want to do much refactoring, you can easily pull the null check out.
if (c.SomeValue == null)
{
btnRecordCall.Enabled = false;
btnAddAction.Enabled = false;
btnProcesss.Enabled = false;
}
else
{
if(c.SomeProperty.Status != 'Y')
{
btnRecordCall.Enabled = false;
}
if((c.SomeProperty.Status != 'Y') &&
(c.SomeOtherPropertyAction != 'Y'))
{
btnAddAction.Enabled = false;
}
if(c.SomeProperty.Processing != 'Y')
{
btnProcesss.Enabled = false;
}
}
If you're looking to refactor instead of shuffle, the wall of boolean testing could be moved in to methods/extension methods of whatever class your object c is an instance of - that way you could say
btnRecordCall.Enabled = c.IsRecordCallAllowed();
Create properties on "c" such as "CanRecordCall", "CanAddAction", "CanProcess" so that your code becomes this:
btnRecordCall.Enabled = c.CanRecordCall;
btnAddAction.Enabled = c.CanAddAction;
btnProcess.Enabled = c.CanProcess;
The "c.SomeValue == null" is a typical response to NullReferenceExceptions. You could improve "c" by initializing its SomeValue property to a null object so that there is never a null reference (just an object that does nothing).
In specific, since you seem to be setting UI elements state, you could consider more of a two-way data binding model where you set up a data context and a control-to-property mapping and let that govern the control state. You can also consider a more heavy-weight solution that would be something like the Validation Application Block from Enterprise Library. There are also some fluent validation projects that you should take a look at.
I'd start by making sure all such code is contiguous. Anything other than this code should be moved before or after the code.
Then, for each reference to a control property, create a corresponding local variable, e.g., processEnabled. Define it before the first if statement. For each such property, move, e.g., btnProcesss.Enabled = false; to the end of this code block, and change "false" to processEnabled. Replace the original with processEnabled = false;.
When the code block has no more references to controls (or to anything else having to do with the UI), select the entire block, from the added variables to the control property sets at the end, and use the Extract Method refactoring. That should leave you with a method that accepts c, and produces values you can later use to set control properties.
You can even get fancier. Instead of individual local variables, define a class that has those "variables" as properties. Do pretty much the same thing, and the extracted method will wind up returning an instance of that class, instead of individual out parameters.
From there, you may start to see more things to clean up in the extracted method, not that you'll have removed anything to do with UI from that code.
I'm guessing the issue here is about 'boolean map' style refactorings, i.e., being able to refactor complementary boolean cases where there might be some gaps and some repetition. Well, if that's what you're after, you can certainly write a tool to do this (it's what I would do). Basically, you need to parse a bunch of if statements and take note of condition combinations that are involved. Then, through some fairly simple logic, you can get your model to spit out a different, more optimized model.
The code you show above is one reason why I love F#. :)
Interestingly, in our current Winforms app, the three conditions would be in three different classes, since each button would be attached to a different Command.
The conditions would be in the CanExecute methods of the commands and control the enable/disable behaviour of the button that triggers the command. The corresponding execution code is in the Execute method of the class.

Categories

Resources