Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I have created a messaging system (basically a simple announcement list with a recipient and a IsRead flag).

This have been done by creating the classics web fields, content type, list schema and list instance. All of this is working as expected.

I want to set the Isread flag (a boolean field) as soon as the user navigates to the dispform page.

In order to reach this goal, I've created a simple webpart with no UI that set the IsRead field on the SPContext.ListItem item :

[ToolboxItemAttribute(false)]
public class MessageSetRead : WebPart
{
    protected override void OnInit(EventArgs e)
    {
        try
        {

            var listItem = SPContext.Current.ListItem;

            // TODO: ensure listitem is a message and exists
            var isReadField = listItem.Fields.GetFieldByInternalName("IsRead");
            var isRead = (bool)listItem[isReadField.Id];
            var recipientField = listItem.Fields.GetFieldByInternalName("AssignedTo");
            var recipientStr = (string) listItem[recipientField.Id];

            var isCurrentUserRecipient =  string.IsNullOrEmpty(recipientStr) ?
                false: 
                new SPFieldUserValue(SPContext.Current.Web, recipientStr).LookupId == SPContext.Current.Web.CurrentUser.ID;


            if (!isRead && isCurrentUserRecipient)

                SPContextUtilities.RunWithElevatedPrivileges((elevatedSite, elevatedWeb) =>
                {
                    using (elevatedWeb.CreateUnsafeUpdateAllowedContext())
                    {
                        var elevatedList = elevatedWeb.Lists[SPContext.Current.ListId];
                        var elevatedListItem = elevatedList.Items.GetItemById(SPContext.Current.ItemId);
                        elevatedListItem[isReadField.Id] = true;
                        elevatedListItem.SystemUpdate(false);
                    }
                });
            }
        }
        catch (Exception exc)
        {
            this.Controls.Clear();
            var errorMessage = new Label();
            errorMessage.Text = HttpUtility.HtmlEncode(exc.ToString());
            errorMessage.Style[HtmlTextWriterStyle.WhiteSpace] = "no-wrap";
            errorMessage.Style[HtmlTextWriterStyle.Color] = "red";
            this.Controls.Add(errorMessage);
        }
    }
}

The webpart is put on the dispform.aspx file from the list schema.xml file :

      <Form Type="DisplayForm"
            Url="DispForm.aspx"
            SetupPath="pages\form.aspx"
            WebPartZoneID="Main">
        <WebParts>
          <AllUsersWebPart WebPartOrder="Integer"
                           WebPartZoneID="Main">
            <![CDATA[
            <webParts>
  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
    <metaData>
      <type name="MyCustomer.Messaging.MessageSetRead.MessageSetRead,    $SharePoint.Project.AssemblyFullName$" />
      <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name="Title" type="string">MessageSetRead</property>
        <property name="Description" type="string">My WebPart</property>
      </properties>
    </data>
  </webPart>
</webParts>

            ]]>
          </AllUsersWebPart>
        </WebParts>
      </Form>

Everything is working but with one gotcha.

When I navigate to the dispform, the IsRead flag is actually set to true, but the user see 'No' in the item. A simple refresh will show the 'Yes' value as expected.

I think this is due to the SPContext.ListItem population which occurs before my Page_Init.

What is the life cycle of the SPContext.ListItem object ?

How should I change my code to see the updated value of my field ?

Thanks

PS: using SP 2010 Enterprise

share|improve this question
add comment

2 Answers 2

I would solve this client side (with Client Object Model) instead. You could either insert a content query / forms web part with some javascript code that sets the property, or use CustomAction in Ribbon or even a delegate control to add a script to additionalPageHead that checks for what list is present and act accordingly.

I dont have any code sample present, but it should be pretty straight forward.

share|improve this answer
add comment

Why do you want to show a field in DisplayForm if it is always True? :)

I would suggest setting SPField.ShowInDisplayForm to false for this field, and you're basically done. It will not be shown in the display form after this, but will appear everywhere else.

And I want to warn you about content editor and javascript approach: using JS hacks to set a value to a field is actually a fragile tactics. Most JS/jQuery hacks use field Title to retrieve the field control, and field titles could be easily changed by a portal user, without even noticing that he actually broke your functionality...

If you still want users to see this always-true-field in your display form, why, you can create another Calculated field, which always evaluates to True, and show it instead :)

share|improve this answer
    
It has to be true only when the user has opened the item. My business requirement is to have a pseudo mail box in a custom application. On the home page, I'll put a list web part where I'll bold the rows when the value is false. As soon as the user click on the list item, it open the full message and set the read flag to true. Hiding this field on the DisplayForm can be an option, but this will prevent non-recipient of the messages to see if the message has been read (my current code does not have the check if the recipient is the current user). –  Steve B Jun 1 '12 at 9:32
    
And moreover, I'm still willing to understand how SPContext works :) this could be useful –  Steve B Jun 1 '12 at 9:33
    
But if you open the form, it should always be true on the form, isn't it? That is what I mean. Don't show it in Display form, show it everywhere else, and leave all your current code in place. –  Andrey Markeev Jun 1 '12 at 9:38
    
It will be true only if the recipient user has opened the form (it's a missing rule by now in my code). If user1, which is the recipient, has never opened the form, user2 have to see "no". –  Steve B Jun 1 '12 at 9:40
    
Ok, now I've got it. But it is reflected neither in your question nor in your code. –  Andrey Markeev Jun 1 '12 at 9:45
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.