Custom field - displayed value
- I created a new field control and I want to customize the value displayed in "DisplayPattern".
The field is a basically a type of a dropdownlist.
The Value property returns a SPFieldLookupValue type, which is used to get the ID and select the item in the list and this part works fine (both New and Edit).
The problem is with Display as it displays values in a "ID;#Text" format and I only want to display the Text.
The FieldControl class inherits from BaseFieldControl and the Field class inherits from SPFieldText.
The ParentType set in xml is Text, but I also tried Lookup, which didn't help.
What's the easiest way of displaying what I need?
Answers
- To save you the trouble, I've created a basic field that mimics your setup to try to find a solution to this problem.
The short answer is that it isn't possible to do what you want to do.
The long answer is:
The XML that's defined in fldTypes.xml is used by the ListViewWebPart to create the list views that you see everywhere in SharePoint. The RenderPattern are basically psuedo-XSLT type code that are interpreted by the ListViewWebPart in a manner that isn't documented and I havent been able to completely determine. However one thing that I have been able to determine, and the reason for my conclusion, is that the RenderPattern makes us of a <LookupColumn> element. However, the code in ListViewWebPart treats this element in the same was as a <Column> element if the ParentType of the field is not Lookup. (Strange but true!)
The handling of elements like Lookup and Column as completely down to the ListViewWebPart and therefore can't be changed. It seems that it has a hardcoded mapping between the parenttype and how the elements are supported. (If you can imagine a switch/case type scenario)
The fix is to change your Field to be of ParentType Lookup, of course you'll also need to change the base class that your field inherits from since having a mismatch between the two will cause the ListViewWebPart to render a blank value. (It seems that there is also a hardcoded reference to the SPFieldLookup class since I've tried implementing everything from SPFieldLookup in a class that derives from SPField and still it doesnt work as expected)
Judjing from the number of posts about similar problems, maybe the real answer to this is to create a whole new ListViewWebPart that does away with this nonsense and replaces it with XSLT or something similar. Although I've got a feeling that'd be a pretty big project! CodePlex anybody?
Hope this helps and saves you wasting any more time trying to get to the bottom of it.
Ch. - My Blog- Marked As Answer byCharlie WuModeratorTuesday, November 10, 2009 2:12 AM
- I've written a blog post that covers rendering for custom fields in more detail. Check it out at: http://www.chaholl.com/archive/2009/11/07/whatrsquos-in-a-renderpattern.aspx
Ch. - My Blog- Marked As Answer byCharlie WuModeratorTuesday, November 10, 2009 2:12 AM
All Replies
- I believe that you have implemented class what is derrived from SPFieldText or something else like SPField****,
that only one thing what you need to do, in this class override method GetValidatedString , that what will return this method will be displayed on AllItems.aspx form and some other places.
Good luck - Yes, it's a SPFieldText.
Overriding GetValidatedString modified the value, which results in the Text being displayed in Display mode, but then it's only the Text that's available in Edit mode, which is not right as then it's the ID that I need.
In other words - I need both ID (Edit and New modes) and Text (View mode).
That's why I'm using the SPFieldLookupValue for the Value property. - Maybe then you need to write own class for holding and working with Value and derrive it from something like SPFieldMultiColumnValue or ***Lookup***
- I'd rather avoid this, as it's a big control and it's already working.
The only think I need to change is the displayed value.
I was also trying to use this:
<RenderPattern Name="DisplayPattern"> <Switch> <Expr> <Column /> </Expr> <Case Value="" /> <Default> <HTML><![CDATA[<A HREF="]]></HTML> <URL Cmd="Lookup"/> <HTML><![CDATA[">Test: ]]></HTML> <Property Select='ValueToDisplay' HTMLEncode="TRUE"/> <HTML><![CDATA[</A>]]></HTML> </Default> </Switch> </RenderPattern>but the ValueToDisplay is empty. Not sure if I'm using it correctly (or should I use FieldProperty?).
Also the generated URL is invalid, but that's a minor issue as I can generate the URL as part of the value to display. - Have you tried to use a same Rendering pattern what using Lookup typed field?
\12\TEMPLATE\XML\FLDTYPES.XML, there you can find Lookup field type definition, if you haven't done it already. It's a pretty big pattern :) - Yes, I tried that, but the exact same patterns does not work, that's why I'm looking for a way to customize it.
- How are you storing your values in your field control? You have an ID and a text value, are they using separate properties or are you storing the combined string?
Ch. - My Blog I don't have separate properties, they are stored as a SPFieldLookupValue object in the Value property.
ID and Text are actually DropDownList's SelectedValue and SelectedItem.Text.- In your code have you added overrides for GetFieldValue, GetFieldValueAsText & FieldValueType?
If so what do they look like?
Ch. - My Blog Here's the GetFieldValue:
public override object GetFieldValue(string value) { if (String.IsNullOrEmpty(value)) { return null; } return value; }
I tried overriding other GetField... methods, but it didn't seem to make any difference, as these methods were never called.Try creating a custom property called TextValue that returns what you want displayed in your display view then change your rendering template to:
<RenderPattern Name="DisplayPattern"> <Property Select="TextValue"/> </RenderPattern>
Ch. - My Blog- I believe there are two controls that make up a field type control. rendering and field. Since you are storing the value as SPFieldLookupValue, don't mess with the field control. Concentrate on the render control. I don't think the RenderPattern is going to help you because you want to change the display method of the rendering itself. If you don't want to mess with this control class you might be able to parse and chop the rendered string to your liking, but I would go the extra mile and subclass the rendering control, I mean its like one method to override.
- I tried that and
- creating a class property doesn't work as it's never accessed (I tried debugging).
- creating a property by calling Field.SetCustomProperty() seems to work, but when the created item is accessed the or Field.GetCustomProperty() returns null and nothing is displayed
Probably the second way is closer to the solution, but something is still missing (I added the property to my fldtypes xml, so that's not it).
Also - I'm not sure if that's the way to go anyway asn these properties seem (not sure if they are) to be Column-specific and not Item-specific, but maybe I'm wrong. In list view the rendering is based in the RenderPattern, altering the rendering control won't make any difference. That'll only affect the new, edit and display properties pages.
The problem here is that the field control is based on a text data type but the control is actually storing a value of SPFieldLookupValue which would generally be used with a field of type SPFieldLookup. The issue here is that the default rendering in list view isn't working correctly (because the item stored a value of type SPFiedlLookupValue), the rendering pattern from a field of type SPFieldLookup doesn't work because the field is derived type SPFieldText. In an ideal world the control would be reimplemented as a derivate of SPFieldLookup but that isn't practical as mentioned above.
It seems to me that the only way to resolve this problem is to fix the RenderPattern.
Ch. - My Blog- Edited byCharlie Holland Tuesday, November 03, 2009 4:32 PMtyps
- As I understand how it works:
it doesn't use any rendering for View, it uses all data what he can retrieve from SQL + RenderPattern, if you haven't any additional properties, than it just retrieves stored value in current case is "ID;#DispName", but especially for this case is created method GetValidatedString, I don't understand why you can't use it. - I'm trying to fix the RenderPattern, but I'm not sure what's wrong with it, why is it not persisting the ValueToDisplay.
Overriding the GetValidatedString not only results in the display value modified from "ID;#Text" to "Text", but also updates the Value to "Text", which later makes impossible to get the ID in Edit mode. - Your right about GetValidatedString but it's used across the board by all the render patterns. The problem is that for the New and Edit rendering the pattern must return id;#value, so changing GetValidatedString would break them. (As I understand it, please correct me if i'm wrong)
I suppose one possibility would be to implement a new rendering control that didnt use GetvalidatedString to render it's value then redo GetValidatedString to return only the text. That way the default render pattern for a text field would work property.
It's all fun and games, can't beat a good puzzle on a Tuesday afternoon!
Ch. - My Blog- Edited byCharlie Holland Tuesday, November 03, 2009 5:02 PMtypos
- Edited byCharlie Holland Tuesday, November 03, 2009 4:44 PMtypos
I found a solution, which seems to work, but is not perfect.
My solutions includes modifying the Value property to return a string, which is actually a link and looks like this:
"<a href='mysite/mylist/DispForm.aspx?ID=myID>myText</a>"
The mysite and mylist are taken from custom properties, so it's all fine and is rendered nicely in Display mode and in Edit mode I can parse the string to get the ID.
It's not perfect, but it works.
The render pattern looks like this:<RenderPattern Name="DisplayPattern"> <Switch> <Expr> <Column /> </Expr> <Case Value="" /> <Default> <HTML><Column /></HTML> </Default> </Switch> </RenderPattern>
Even though it works I'm still looking to find another way of doing this by using RenderPattern only.- Can you post your source code? Or at least enough of it so that we can replicate the problem?
I'd quite like to have a mess around with this one to see if we can't find a better way
Ch. - My Blog - I'll try to create a separate simplified control (there's too much going on in this one) for this purpose and post the code, but that's probably going to happen tomorrow.
- To save you the trouble, I've created a basic field that mimics your setup to try to find a solution to this problem.
The short answer is that it isn't possible to do what you want to do.
The long answer is:
The XML that's defined in fldTypes.xml is used by the ListViewWebPart to create the list views that you see everywhere in SharePoint. The RenderPattern are basically psuedo-XSLT type code that are interpreted by the ListViewWebPart in a manner that isn't documented and I havent been able to completely determine. However one thing that I have been able to determine, and the reason for my conclusion, is that the RenderPattern makes us of a <LookupColumn> element. However, the code in ListViewWebPart treats this element in the same was as a <Column> element if the ParentType of the field is not Lookup. (Strange but true!)
The handling of elements like Lookup and Column as completely down to the ListViewWebPart and therefore can't be changed. It seems that it has a hardcoded mapping between the parenttype and how the elements are supported. (If you can imagine a switch/case type scenario)
The fix is to change your Field to be of ParentType Lookup, of course you'll also need to change the base class that your field inherits from since having a mismatch between the two will cause the ListViewWebPart to render a blank value. (It seems that there is also a hardcoded reference to the SPFieldLookup class since I've tried implementing everything from SPFieldLookup in a class that derives from SPField and still it doesnt work as expected)
Judjing from the number of posts about similar problems, maybe the real answer to this is to create a whole new ListViewWebPart that does away with this nonsense and replaces it with XSLT or something similar. Although I've got a feeling that'd be a pretty big project! CodePlex anybody?
Hope this helps and saves you wasting any more time trying to get to the bottom of it.
Ch. - My Blog- Marked As Answer byCharlie WuModeratorTuesday, November 10, 2009 2:12 AM
- I've written a blog post that covers rendering for custom fields in more detail. Check it out at: http://www.chaholl.com/archive/2009/11/07/whatrsquos-in-a-renderpattern.aspx
Ch. - My Blog- Marked As Answer byCharlie WuModeratorTuesday, November 10, 2009 2:12 AM

