Databound PivotControl jumps over pivots when they come from similar objects [WP7] - c#

I have a PivotControl with bindings. Everything worked well until I added a pivot two pivots with the same title, let's call them C and C', and A an B two different pivots, ordered like this: AC'BC. Now, when I try to go from B to C everything is OK. But when I go from A to C, it does strange things: doesn't move, moves the titles but not the content... weird.
I debugged the SelectionChanged event in the PivotControl, and it's even weirdest. It's called two times: the first, a transition from C to another pivot and then another call which contains the right transition, from A to C.
I've tried everything. The databinding is a list of structs, like this:
struct Resource
{
public someenum Type;
public string Data;
public string Identifier { get {...} set {...} }
public UserToken User;
}
The title of the pivot is set by a IValueConverter, which takes the string Identifier (which is a function of Type, Data and User) as the parameter. I changed it to make the titles always different, but it still does not work. For example, when Type and Data are the same there are error, although Identifier and User are different.
I have written both operators == and != for Resource, and also for UserToken. They behave as they should, but still does this weird transition.

Stating the obvious: give them different names.
If they are different you should give them different names. Just post-fix the name with a counter.
EDIT
From the MSDN:
Name is one of the very few dependency properties that cannot be
animated (IsAnimationProhibited is true in metadata), because the name
itself is vital for targeting an animation. Data binding a Name is
technically possible, but is an extremely uncommon scenario because a
data-bound Name cannot serve the main intended purpose of the
property: to provide an identifier connection point for code-behind.

Just found the answer. After a lot of googling, I noticed that maybe GetHashCode had something to do in this mess. I modified the definition of getHashCode in the struct and, voilá! It works smoothly :)
Just a tip: to get a good GetHashCode function return a XOR of the volatile parameters of the function. In my case, the code was this:
Type.GetHashCode() ^ Data.GetHashCode() ^ User.GetHashCode();

Related

Declaring a property with an empty set in C#

I am using entity framework database first and extending the AutoGenerated partial classes. Is the following alright if I need to also set the property in my application based on certain scenarios? It just feels strange because I am usually setting a private property in my set, but don't think I need to here with EF.
public string FullName
{
get
{
return string.Format("{0} {1}", FirstName, LastName);
}
set
{
}
}
In my application FullName is a bound field in a grid. When I bind the grid from the database it works fine as a read-only property. But there is an instance where I have to dynamically create an objectlist of CustomerContact and pass it to another page in a Session variable and bind the grid in memory on the new page. Since the bound field for the same column in the grid on the new page needs to be FullName it seems like I have no option but to allow a Set on this property...
Based on the comments. No you should not leave it empty.
Think about it from a user point of view.
You can say MyThingy.FullName = "Fred Blogs". It compiles, it throws no exceptions and does absolutely nothing.
Other people's code, which includes your own in a couple of months, is hard enough to understand without drilling big holes in your cortex before you start.
To beef up from your last comment. No it doesn't make sense to have one class that has two completely different behaviours. There are lots of ways to deal with this sort of scenario, but making one object that implements both behaviours poorly isn't a good choice.
Hard to say which option would be best, but a DTO (Data Transfer Object) with a converter from and perhaps to the EF representation would be a much better solution than leaving a huge hole in the logic to fall into later.

Is it possible to create a class template and select a C# property when the function is called?

Does anyone know if the following is possible to pass in a List<> of objects to a function and specify which property the function should use within each object that its working with ?
I have a class that works with a specific property of an object throughout the class, but I dont want to create multiple copies of the same class to work with different properties of that object. I thought about using Linq, but I dont see a way to specify which property to use in other functions of the manipulation class.
I was thinking there has to be a more elegant way to do this instead of creating the same class to handle each property. I thought about using Reflection to tell the function which property to work with but that gets ugly really quick
Example psuedo code :
class Store
{
int amount;
int id;
int serial;
}
class AggregationMethods
{
bool Has3Values( List<Store> places /* some other param to specify which property to use*/)
{
// do something with Store.amount or Store.id
}
// other functions to work with Store.amount or Store.id or Store.serial
}
In your case, they're all int values - so you could just retain a Func<Store, int> or pass it into each method. It becomes slightly harder if you need to work over multiple types, but we don't really have enough information to comment further.
It's also not clear whether you would expect two have multiple instances of AggregationMethods (e.g. one for amounts, one for IDs etc) or whether these would really be static methods. If you're using instances, then you could keep the projection as a member variable, and apply it within each method.
It's worth noting that the properties you've given probably don't really make sense to apply the same aggregations - for example, while summing amounts makes sense, it's meaningless to sum IDs.

How to solve cast issues in ValidationRule classes' properties?

I need to create a few tests for the user roles in a web application. To minimize the description, one of the tests involves checking if a menu entry is displayed or not for an user.
For this test, I use a table called UserRoles, that looks like this:
sUserName bDoesntHaveMenuX
User1 1
User2 0
User3 1
bDoesntHaveMenuX is of type bit.
I have a class derived from ValidationRule that checks if a certain text is present in a page, based on a XPath expression to locate the node where to look for the text.
The public properties of this class are:
string XPathExpression
string Text
bool FailIfFound
The last one dictates if the rule should fail if the text is found or not found.
In the test I added a datasource for the table mentioned in the beginning, called DS.
For the request I'm interested in I added a new instance of my validation rule class, with the following values:
Text=MenuX
XPathExpression=//div[#id='menu']//td
FailIfFound={{DS.UserRoles.bDoesntHaveMenuX}}
Unfortunately, this doesn't work.
The reason seems to be that the data binding process creates a context variable
DS.UserRoles.bDoesntHaveMenuX has the value "False" or "True". The value is a string, so the binding results in a casting error.
My options, as far as I can think of, are:
Change the validation rule to accept strings for FailIfFound. Not a valid
option, for 2 reasons: it's a hack and the same rule is used in
other places.
Make a new validation rule that will use the above mentioned one,
and implement the FailIfFound as string. I also don't like this, for
the same reason as above. It's a hack.
Make the test coded and do the proper cast before passing the data
to the validation rule. I don't like this one because I prefer to
have the test as coded only if there is no other way.
Which brings me to the question. Is there another way?
Thank you.
So the fundamental issue is that you have no control over how the data-binding treats the 'bit' data type, and it's getting converted to string instead of bool.
The only solution I can think of (which is sadly still a bit of a hack, but not so egregious as changing FailIfFound to string) is to create a WebTestPlugin, and in the PreRequestDataBinding or PreRequest event, convert the value from string to bool. Don't forget to add the plugin to your test(s) (easy mistake I have made).
Then when the validation rule is created it should pick up the nice new bool value and work correctly.
e.g.
string val = e.WebTest.Context["DS.UserRoles.bDoesntHaveMenuX"].ToString();
e.WebTest.Context["DS.UserRoles.bDoesntHaveMenuX"] = (val == "True");
I didn't actually try this... hope it works.
EDIT: round two... a better solution
Change the FailIfFound property to string (in a subclass as you mentioned), so it can work properly with data-binding.
Implement a TypeConverter that provides a dropdown list of valid values for the property in the rule's PropertyGrid (True, False), so in the GUI it looks identical to the rule having FailIfFound as a bool. You can still type your own value into the box when necessary (e.g. for data-binding).
Add the path of the .dll containing the TypeConverter code to your test project's References section.
This is what I have started doing and it is much more satisfying than having to type 'True' or 'False' in the property's edit box.

Asp Composite control child control (radiobutton) losing checked value

I am working on a quiz control in asp.net with dynamically created questions and options.
The main control is basically a container to hold all of the questions.
In design view users can add questions through a custom Collection Editor.
Everytime i add a question to the collection editor list it generates a question tag for me.
Inside each question object is a label and a n amount of Option objects that inherit the Radiobutton Control. Each of these Option objects in turn represent a option the user can select for each question.
This all works except i am now at the part where i want to be able to read the Checked value of each radiobutton. When i want to implement this quiz inside a page and check the questions i want to put a button in this page and call the following function that is inside the control:
$
public String checkQuestions()
{
if (questions != null)
{
foreach (Question question in questions)
{
options = question.readOptions();
int i = 0;
foreach (Option option in options)
{
testLabel.Text = option.Checked.ToString(); // test purposes only
}
}
}
return errors;
}
However once i select a radiobutton and click on the submit button the Checked value will always turn out false for all of the options.
Basically it is losing its checked value after a Postback and i am just stuck in trying to solve it.
Would appreciate it if anyone could point me in the right direction.
At a first glance, there are two things I'd check. Firstly, make sure you're implementing IPostBackDataHandler. this requires you to implement two methods, LoadPostData and RaisePostDataChangedEvent. At my first guess, the first one is probably the source of your problem.
Handling postback manually
LoadPostData takes a string postDataKey and a NameValueCollection postCollection and returns a bool indicating whether or not the value has changed as a result of the postback. You don't need to implement this the way .Net originally intends, for example I created a control that held several radio buttons (that for reasons that aren't important here couldn't simply be a RadioButtonList control) and so made sure they were all named by a property string GroupName and inspected the postCollection for that GroupName:
public bool LoadPostData(string postDataKey,
System.Collections.Specialized.NameValueCollection postCollection)
{
bool oldValue = _isChecked;
postCollection = HttpContext.Current.Request.Form; // See note below
_isChecked = (postCollection[this.GroupName] == this.Text);
return oldValue == _isChecked;
}
You'll notice that I'm redefining the postCollection here; this is because postCollection only contains a subset of the HttpRequest.Form corresponding to what ASP.Net thinks your control should care about. As you're also building a composite control here, you probably want to do the same.
Don't worry if this doesn't work first time round; it's worth stepping through what gets passed into this method in debug mode (or outputting things to the HttpContext.Trace, which I often find easier) to see why your code isn't quite what you need.
A quick caveat
One last thing: LoadPostData is only called if the posted form contains a field with a name which matches the UniqueID of your control. As your control is a composite control, you might want to cowboy this slightly, like so:
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
writer.WriteBeginTag("input");
writer.WriteAttribute("type", "hidden");
writer.WriteAttribute("name", this.UniqueID);
writer.WriteAttribute("value", "post");
writer.Write(" />");
}
It's a dirty hack, but it'll work ;o)
Handling viewstate manually
If handling the postback manually doesn't solve your problem, it might be that you need to mess with the viewstate of your control. Don't worry, this is nowhere near as scary as it seems, provided you follow a few simple rules.
To handle your viewstate manually, you just need to override two methods called, obviously enough, LoadViewState and SaveViewState. The first takes an object of viewstate to inflate and the other returns that same object structure. If you make your SaveViewState override return something containing the structure you need to save all the important properties that need persisting, then you just inflate it again in your LoadViewState method.
Here's where the first of the cunning tricks comes up. There are certain datatypes that you should use for saving viewstate and you should never use any other type (because other types are stored really inefficiently). The types that will probably be most useful to you are System.Web.UI.Pair, System.Web.UI.Triplet and our old friends System.Collections.ArrayList and System.Collections.Hashtable. Pairs and Triplets simply store two or three values of type object; ArrayLists are effectively a List<object>.
I'd guess that, in your circumstance, you probably want to store either (1) an ArrayList of boolean flags, storing the "checkedness" of your radiobuttons or (2) an ArrayList of strings or ints, storing the IDs or index of the checked radiobuttons.
In the control I mentioned earlier, I just needed to store the checkedness and the Text property, so my LoadViewState and SaveViewState methods looked like this:
protected override void LoadViewState(object savedState)
{
Pair state = savedState as Pair;
if (state != null)
{
_isChecked = state.First as Nullable<bool> ?? false;
this.Text = state.Second as string;
}
}
protected override object SaveViewState()
{
return new Pair(_isChecked, this.Text);
}
Again, if this doesn't work first time, you almost certainly want to step through the code or throw things into the Trace. Importantly, you probably want to avoid throwing Exceptions from these methods, in case your viewstate is corrupt or non-existent or something.
Further reading on viewstate
There are a couple of very useful articles I keep bookmarked for when I'm messing with viewstate. The first one explains about why you should only store certain types in the viewstate (like using ArrayList and Hashtable, rather than List<T> and Dictionary<TKey, TValue>) and the second is a good in-depth explanation of how all this viewstate stuff actually works.
Don't let the BinaryFormatter get at it!
Truly understanding ViewState
I hope all this helps resolve your problem.

Is it bad practice to use an enum that maps to some seed data in a Database?

I have a table in my database called "OrderItemType" which has about 5 records for the different OrderItemTypes in my system. Each OrderItem contains an OrderItemType, and this gives me referential integrity. In my middletier code, I also have an enum which matches the values in this table so that I can have business logic for the different types.
My dev manager says he hates it when people do this, and I am not exactly sure why. Is there a better practice I should be following?
I do this all the time and I see nothing wrong with this. The fact of the matter is, there are values that are special to your application and your code needs to react differently to those values. Would your manager rather you hard-code an Int or a GUID to identify the Type? Or would he rather you derive a special object from OrderItem for each different Type in the database? Both of those suck much worse than an enum.
I don't see any problem in having enum values stored in the database, this actually prevents your code from dealing with invalid code types. After I started doing this I started to have fewer problems, actually. Does your manager offer any rationale for his hatred?
We do this, too. In our database we have an Int column that we map to an Enum value in the code.
If you have a real business concern for each of the specific types, then I would keep the enum and ditch it in the database.
The reason behind this approach is simple:
Every time you add an OrderType, you're going to have to add business logic for it. So that justifies it being in your business domain somewhere (whether its an enum or not). However, in this case having it in the database doesn't do anything for you.
I have seen this done for performance reasons but I think that using a caching mechanism would be perferable in most cases.
One alternative to help with the synchronization of the database values and the business logic enum values would be to use the EnumBuilder class to dynamically generate a .dll containing the current enum values from the database. Your business logic could then reference it, and have intellisense-supported synchonized enum values.
It's actually much less complicated than it sounds.
Here's a link to MSDN to explain how to dynamically build the enum.
http://msdn.microsoft.com/en-us/library/system.reflection.emit.enumbuilder.aspx
You just have to sub in the database access code to grab the enum values:
One more vote for you, I also use mapping database int <-> application enum, in addition, I usually describe my enums like this:
public enum Operation
{
[Description("Add item")]
AddItem = 0,
[Description("Remove item")]
RemoveItem = 1
}
which leaves me absolutely free to add new values without need to change database and with a very short workaround I can work i.e. with lists containing descriptions (that are very strongly tied to values!) - just a little bit of reflection reaches the goal!
In code, you can typically just add a property like this:
public class Order
{
public int OrderTypeInt;
public OrderTypeEnum OrderType
{
get { return (OrderTypeEnum)OrderTypeInt; }
set { OrderTypeInt = (int)value; }
}
}

Categories

Resources