Save value of custom field type - c#

I am new to SharePoint developement and have a few startup problems which I hope you will help me with.
I am trying to make a custom field type and I am using WPS builder to create the project. Right now I have the following files which are all compiling just fine :)
SuperLookup3.cs
SuperLookup3Control.cs
SuperLookup3FieldEditor.cs
SuperLookup3FieldEditor.ascx (controltemplate)
fldtypes_SuperLookup3.xml (XML)
I have tried look at this example but I just can't get it to work.
My questions
How is the relationsships between the files?
I can see an override of UpdateFieldValueInItem() which is setting the value to the selected item of a dropdown list. But this method is never called (when debugging). How can this be?

Some general advice would be to post this question to the SharePoint Stack Exchange site (if this answer is unsatisfactory), since there are a lot more SharePoint developers there.
From what I understand of that example, it seems to be quite a complex Custom Field Type to start with (given that it has multiple values). There's a good straightforward and pretty well explained tutorial on MSDN that you might want to try out: Walkthrough: Creating a Custom Field Type
Here's a brief explanation of your files (and the classes they contain):
This is the main class of your field, which derives from the SharePoint field base class (SPField). Your naming seems to indicate you're creating a lookup derivative; if so, you may wish to derived from SPFieldLookup.
This is the class the creates the form control displayed on a list item's New, Edit, and Display forms (but not the List View). It's a go-between for the forms and the item's value for this field.
&
This is the section displayed on the Add/Edit Column page. I would expect 3. to have the ending '.ascx.cs' instead of '.cs', since it is the code-behind for 4.; which may be the cause of your problem. This control sets up your field; associating the class in 1. to the list.
This is the field declaration. It says to SharePoint "Hey, I've created my own field; go look here to find it.", and directs SharePoint to the class in 1., which makes the field available on the Add Column page.

Related

Replace ListPickerPage with custom Page

I added the Windows Phone Toolkit with Nuget into my project.
Now I want to replace the default ListPickerPage with a custom page like this can be achieved for the DatePickerPage. (http://blogs.msdn.com/b/delay/archive/2010/09/21/there-are-lots-of-ways-to-ask-for-a-date-creating-custom-datepicker-timepicker-experiences-is-easy-with-the-windows-phone-toolkit.aspx)
Unfortunately this page does not provide an interface from which I could inherit.
The ListPicker.cs seems to have the reference hard coded:
private ListPickerPage _listPickerPage;
Even though it supports the PickerPageUri property.
I copied the ListPickerPage.xaml and code behind from the Source Repository and provided the path to this page as PickerPageUri.
The Page is opened but contains no content!
I think the reason is this part of code in the ListPicker.cs:
_listPickerPage = e.Content as ListPickerPage;
My class is not a "ListPickerPage" and therefore the reference remains null and no values will be set.
Next step I tried was to inherit from ListPickerPage to get the cast done.
Problem here: the public properties Items and some others have "private set" properties.
At the end, I always ended up with an empty target page.
Google + StackOverflow stated many times that one has to copy the page and simply refer to it via PickerPageUri, but this alone seems not to work.
Has anybody managed to get an own ListPickerPage in his project?

MEF update exported part metadata (the metadata view is invalid because property has a property set method)

I have an application and I'm using MEF to compose it. I want to know if it is possible to update the Metadata information of the parts after they were imported.
The reason to do this is the following: I display the imported parts' name and an typeof(int) property in a ListBox, and they are not loaded until the corresponding ListBoxItem is selected (pretty standard). Now I want to update the Metadata info of one part when some event raises, so the displayed info in the ListBox is somethind like "[Part name] ([new number])".
I'm importing the metadata as an Interface that defines it's info, but when I set the int property to be editable (with a set accesor) I receive the following execption at composition time:
"The MetadataView 'myMetadataInterface' is invalid
because property 'myInt' has a property set method."
Is there ANY way to achieve this? Or is the metadata ALWAYS read only once the part is created?
I know this question looks weird, but it doesn't make it any less difficult and therefore interesting ;-)
EDIT (based on Lee's answer, in order to keep people to the core of the question)
I just want to know if it is possible to update a Metadata property after the part is composed, but before it is actually loaded (HasValue == false). Don't worry about filtering or finding the part.
I added a property to the export inteface, which is meant only to be represented in the UI and to be updated, this property has no other function and the parts are not filtered by it.
Thanks
Metadata filtering and DefaultValueAttribute
When you specifiy a metadata view, an implicit filtering will occur to
match only those exports which contain the metadata properties defined
in the view. You can specify on the metadata view that a property is
not required, by using the
System.ComponentModel.DefaultValueAttribute. Below you can see where
we have specified a default value of false on IsSecure. This means if
a part exports IMessageSender, but does not supply IsSecure metadata,
then it will still be matched.
citation
Short Version (EDITED in after question edit).
You shouldn't ever need to update metadata at runtime. If you have some data that should be updated and belongs to a mef part, you need to choose to either have it be updated by recompiling, or store that data in a flexible storage outside of the dll. There's no way to store the change you made in the dll without recompiling, so this is a flawed design.
Previous post.
Altering values on the view would by lying about the components loaded. Sure the metadata is just an interface to an object that returns initialized values; sure you can technically update those values, but that's not the purpose of metadata.
You wouldn't be changing the Name field of an instance of Type. Why not? Because it's metadata. Updating metadata at runtime would imply that the nature of the instance of real data is somehow modified.
This line of code, if possible, wouldn't introduce the Triple type.
typeof(Double).Name = "Triple";
var IGotATriple = new Triple();
If you want to alter values, you need to just make another object with that information and bind to that. Metadata is compiled in. If you change it after a part is loaded, it doesn't change anything in the part's source, so you'd be lying. (unless you're going to have access to the source-code and you change it there and recompile).
Let's look at an example:
[Export(typeof(IPart))]
[ExportMetadata("Part Name","Gearbox")]
[ExportMetadata("Part Number","123")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class GearBoxPart : Part { public double GearRatio ... }
Now, let's assume that you had a UI that showed available parts and their numbers. Now, the manufacturer changes the part number for whatever reason and you want to update it. If this is possible, you might want to consider storing part number in a manifest or database instead. Alternatively you'd have to recompile every time a part number changes.
Recompile is possible. You have a controller UI that does the above, but instead of updating the metadata, you submit a request to rebuild the part's codefile. The request would be handled by parsing the codefile, replacing the part number, then sending off for a batch recompile and redistribute the new dll. That's a lot of work for nothing IMO.
So, you setup a database. Then you change the object metadata to this.
[ExportMetadata("OurCompanyNamePartNumber","123")]
Then you have a database/manifest/xml that maps your unique permanent static part number that your company devises to the current part number. Modifications in your control UI update the database/manifest/xml.
<PartMap>
<PartMapEntry OurCompanyNamePartNumber="123" ManufacturerPartNumber="456"/>
...
</PartMap>
Then the end-user UI does lookups for the part by manufacturer part number, and the mef code looks in the PartMap to get the mef part number.

Dynamic form with no real OOP or objects?

I am tacking a large refactor of a project, and I had asked this question to confirm/understand the direction I should go in and I think I got the answer that I wanted, which is not to throw away years worth of code. So, now begins the challenge of refactoring the code. I've been reading Martine Fowler and Martin Feathers' books, and they have a lot of insight, but I am looking for advice on the ultimate goal of where I want the application to be.
So to reiterate the application a little bit, its a dynamic forms system, with lots of validation logic and data logic between the fields. The main record that gets inserted is the set of form fields that is on the page. Another part of it is 'Actions' that you can do for a person. These 'Actions' can differ client by client, and there are hundreds of 'Actions'. There is also talk that we can somehow make an engine that can eventually take on other similar areas, where a 'person' can be something else (such as student, or employee). So I want to build something very de-coupled. We have one codebase, but different DBs for different clients. The set of form fields on the page are dynamic, but the DB is not - it is translated into the specific DB table via stored procs. So, the generic set of fields are sent to the stored proc and the stored proc then decides what to do with the fields (figure out which table it needs to go to). These tables in fact are pretty static, meaning that they are not really dynamic, and there is a certain structure to it.
What I'm struggling specifically is how to setup a good way to do the dynamic form control page. It seems majority of the logic will be in code on the UI/aspx.cs page, because its loading controls onto the webpage. Is there some way I can do this, so it is done in a streamlined fashion, so the aspx.cs page isn't 5000 lines long? I have a 'FORM' object, and one of the properties is its' 'FIELDS'. So this object is loaded up in the business layer and the Data layer, but now on the fron end, it has to loop through the FIELDS and output the controls onto the page. Also, someway to be able to control the placement would be useful, too - not sure how do get that into this model....
Also, from another point of view - how can I 'really' get this into an object-oriented-structure? Because technically, they can create forms of anything. And those form fields can represent any object. So, for example, today they can create a set of form fields, that represent a 'person' - tomorrow they can create a set of form fields that represent a 'furniture'. How can I possibly translate this to to a person or a furniture object (or should I even be trying to?). And I don't really have controls over the form fields, because they can create whatever....
Any thought process would be really helpful - thanks!
How can I possibly translate this to to a person or a furniture object
(or should I even be trying to?)
If I understand you correctly, you probably shouldn't try to convert these fields to specific objects since the nature of your application is so dynamic. If the stored procedures are capable of figuring out which combination of fields belongs to which tables, then great.
If you can change the DB schema, I would suggest coming up with something much more dynamic. Rather than have a single table for each type of dynamic object, I would create the following schema:
Object {
ID
Name
... (clientID, etc.) ...
}
Property {
ID
ObjectID
Name
DBType (int, string, object-id, etc.)
FormType ( textbox, checkbox, etc.)
[FormValidationRegex] <== optional, could be used by field controls
Value
}
If you can't change the database schema, you can still apply the following to the old system using the stored procedures and fixed tables:
Then when you read in a specific object from the database, you can loop through each of the properties and get the form type and simple add the appropriate generic form type to the page:
foreach(Property p in Object.Properties)
{
switch(p.FormType)
{
case FormType.CheckBox:
PageForm.AddField(new CheckboxFormField(p.Name, p.Value));
break;
case FormType.Email:
PageForm.AddField(new EmailFormField(p.Name, p.Value));
break;
case FormType.etc:
...
break;
}
}
Of course, I threw in a PageForm object, as well as CheckboxFormField and EmailFormField objects. The PageForm object could simply be a placeholder, and the CheckboxFormField and EmailFormField could be UserControls or ServerControls.
I would not recommend trying to control placement. Just list off each field one by one vertically. This is becoming more and more popular anyway, even with static forms who's layout can be controlled completely. Most signup forms, for example, follow this convention.
I hope that helps. If I understood your question wrong, or if you'd like further explanations, let me know.
Not sure I understand the question. But there's two toolboxes suitable for writing generic code. It's generics, and it's reflection - typically in combination.
I don't think I really understand what you're trying to do, but a method using relfection to identify all the properties of an object might look like this:
using System.Reflection;
(...)
public void VisitProperties(object subject)
{
Type subjectType = subject.GetType();
foreach (PropertyInfo info in subjectType.GetProperties()
{
object value = info.GetValue(subject, null);
Console.WriteLine("The name of the property is " + info.Name);
Console.WriteLine("The value is " + value.ToString());
}
}
You can also check out an entry on my blog where I discuss using attributes on objects in conjunction with reflection. It's actually discussing how this can be utilized to write generic UI. Not exactly what you want, but at least the same principles could be used.
http://codepatrol.wordpress.com/2011/08/19/129/
This means that you could create your own custom attributes, or use those that already exists within the .NET framework already, to describe your types. Attributes to specify rules for validation, field label, even field placement could be used.
public class Person
{
[FieldLabel("First name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(1)]
[FormRow(1)]
public string FirstName{get;set;}
[FieldLabel("Last name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(2)]
[FormRow(1)]
public string LastName{get;set;}
}
Then you'd use the method described in my blog to identify these attributes and take the apropriate action - e.g. placing them in the proper row, giving the correct label, and so forth. I won't propose how to solve these things, but at least reflection is a great and simple tool to get descriptive information about an unknown type.
I found xml invaluable for this same situation. You can build an object graph in your code to represent the form easily enough. This object graph can again be loaded/saved from a db easily.
You can turn your object graph into xml & use xslt to generate the html for display. You now also have the benefit of customising this transform for differnetn clients/versions/etc. I also store the xml in the database for performance & to give me a publish function.
You need some specific code to deal with the incoming data, as you're going to be accessing the raw request post. You need to validate the incoming data against what you think you was shown. That stops people spoofing/meddling with your forms.
I hope that all makes sense.

Requires a generic approach to validate control of ASP.Net form

I have a B2B we app having lots of forms taking input from registered users. So validation is mandatory there. I am using 3 tier architecture for my app. I am just ignoring server validation controls and client side validations. Instead i am thinking of Code Behind based validation, which i know will increase hit to my server, but too is most secure, if I am not wrong.
So what i am thinking is,
to enumerate all the controls of the page and check their validity. But this wayI can check only whether it is empty or not. Also I have to write it on each and every page.
Another approach, if i can set the maxlength , mandatory etc somewhere in my Model Layer where I have skeleton classes,and compare it while save button hit and tell what is missing and where.
Some common method that will take entire page controls as array of controls and check for validity...
Please guide me which one is possible or any other good solution.So that i can avoid code repetitions.
Model Layer means
public class Employee
{
public string Name {get;set;}
}
You can add a set of controls that inherit from ASP.NET controls, only with (a)additional type classification. For example: TextBox that accepts an attribute of DataType (enum) and values like: int, double, email etc. Another idea is for int type add a min/max values (i.e 15-32). And (b) a Validate function that returns true/false if the value matches the datatype.
Then, create a page base that inherits from Page and exposes a function called ValidateAllMyControls that iterates through all those special controls that are in use in the current form and calls the Validate function for each one. If one of them returns false - the form is not valid. :)

C# property attributes

I have seen the following code:
[DefaultValue(100)]
[Description("Some descriptive field here")]
public int MyProperty{...}
The functionality from the above snippit seems clear enough, I have no idea as to how I can use it to do useful things. Im not even sure as to what name to give it!
Does anyone know where I can find more information/a tutorial on these property attributes?
I would be also interested in any novel / useful tasks this feature can do.
The functionality from the above
snippit seems clear enough,
Maybe not, as many people think that [DefaultValue()] sets the value of the property. Actually, all it does to tell some visual designer (e.g. Visual Studio), what the code is going to set the default value to. That way it knows to bold the value in the Property Window if it's set to something else.
People have already covered the UI aspect - attributes have other uses, though... for example, they are used extensively in most serialization frameworks.
Some attributes are given special treatment by the compiler - for example, [PrincipalPermission(...)] adds declarative security to a method, allowing you to (automatically) check that the user has suitable access.
To add your own special handling, you can use PostSharp; there are many great examples of using PostSharp to do AOP things, like logging - or just code simplification, such as with automatic INotifyPropertyChanged implementation.
They are called Attributes, there is a lot of information in msdn, e.g. http://msdn.microsoft.com/en-us/library/z0w1kczw.aspx
In general they don't "do" anything on their own, they are used by some other code that will use your class. XmlSerialization is a good example: XmlSerializer (provided by Microsoft as part of the framework) can almost any class (there are a number of requirements on the class though) - it uses reflection to see what data is contained in the class. You can use attributes (defined together with XmlSerializer) to change the way XmlSerializer will serialize your class (e.g. tell it to save the data as attribute instead of an element).
The ones in your example is used by the visual designer (i.e. MS Expression Blend and Visual Studio designer) to give hints in the designer UI.
Note that they are metadata and will not affect the property logic. Setting DefaultValue for instance will not set the property to that value by default, you have to do that manually.
If you for some reason want to access these attributes, you would have to use reflection.
See MSDN for more information about designer attributes.
We use it to define which graphical designer should be loaded to configure
an instance of a specific type.
That is to say, we have a kind of workflow designer which loads all possible command
types from an assembly. These command types have properties that need to be configured,
so every command type has the need for a different designer (usercontrol).
For example, consider the following command type (called a composite in our solution)
[CompositeMetaData("Delay","Sets the delay between commands",1)]
[CompositeDesigner(typeof(DelayCompositeDesigner))]
public class DelayComposite : CompositeBase
{
// code here
}
This is information is used in two places
1) When the designer creates a list of commands, it uses the CompositeMetaData
to display more information about the command.
2) When the user adds a command to the designer and the designer creates
an instance of that class, it looks at the CompositeDesigner property,
creates a new instance of the specified type (usercontrol) and adds it
to the visual designer.
Consider the following code, we use to load the commands into our "toolbar":
foreach (Type t in assembly.GetExportedTypes())
{
Console.WriteLine(t.Name);
if (t.Name.EndsWith("Composite"))
{
var attributes = t.GetCustomAttributes(false);
ToolboxListItem item = new ToolboxListItem();
CompositeMetaDataAttribute meta = (CompositeMetaDataAttribute)attributes
.Where(a => a.GetType() == typeof(Vialis.LightLink.Attributes.CompositeMetaDataAttribute)).First();
item.Name = meta.DisplayName;
item.Description = meta.Description;
item.Length = meta.Length;
item.CompositType = t;
this.lstCommands.Items.Add(item);
}
}
As you can see, for every type in the assembly of which the name ends with "Composite",
we get the custom attributes and use that information to populate our ToolboxListItem instance.
As for loading the designer, the attribute is retreived like this:
var designerAttribute = (CompositeDesignerAttribute)item.CompositType.GetCustomAttributes(false)
.Where(a => a.GetType() == typeof(CompositeDesignerAttribute)).FirstOrDefault();
This is just one example of how you might be able to use custom attributes,
I hope this gives you a place to start.
These attributes customize the design time experience.
http://msdn.microsoft.com/en-us/library/a19191fh.aspx

Categories