Generally speaking, you use the StandardSetController. Here's a simple example of how you'd do this:
<apex:page standardController="Opportunity" recordSetVar="Opps">
<apex:form>
<apex:pageBlock>
<apex:pageBlockSection>
<apex:inputField value="{!Opportunity.OwnerId}" />
</apex:pageBlockSection>
<apex:pageBlockTable value="{!selected}" var="opp">
<apex:column value="{!Opp.Name}" />
</apex:pageBlockTable>
<apex:pageBlockButtons>
<apex:commandButton action="{!save}" value="Save" />
</apex:pageBlockButtons>
</apex:pageBlock>
</apex:form>
</apex:page>
Create a new button, type List (with Multi-select buttons), then add it to a list view. Afterwards, users can click boxes in the list, use the button, and select a new owner. Up to 200 records can be modified at once this way.
As per the comments, here's some additional info.
The recordSetVar, here called Opps
, is used to list all of the opportunities from a query or list view. This isn't practical here, because we're only interested in showing the user the records they've selected. We could use this to provide an interactive session where the user selects records they want to use (via the record's selected
attribute). In this case, we're simply using recordSetVar
to switch from the StandardController to the StandardSetController, so we can leverage some of its features.
This leads us to the next point. Unlike the StandardController, in the StandardSetController, the main record variable refers to a "prototype" object. When we specify {!Opportunity.OwnerId}
, we're specifying that we want to set all of the selected records to the value specified by this field. In this case, when we set the Owner field, all selected records will be set to the new value. You can have up to 200 records selected, and they will all be affected by this new value.
The actual merge field {!selected}
is bound to the StandardSetController's getSelected
method, which just returns a list of the selected elements. If you're using the selected
attribute on records, you can dynamically modify this list. We're not using that technique though, because the values are set by the user's selections in the list view.
Finally, the values for the selected list come from the built-in feature that allows users to check boxes on a list view or related list. The platform automatically injects the correct values that were selected from the prior screen. This feature allows Professional Edition users to code mass actions without Apex Code, which is definitely a powerful feature.
You could also choose to expose a list of List Views via getListViewOptions, which can be bound to the filterId attribute of the StandardSetController, allowing users to change views and select records they wish to modify on-the-fly. This is another advanced use case for the StandardSetController for a mass action page that does not require any custom Apex Code.
Best Answer
Assuming your not adverse to a bit of Apex I would recommend you use the StandardSetController for most of this. It is specifically designed to be used with VF pages that extend the ListView and selection functionality. Here is an example I created for you, called Bump Case Priority.
It presents a page to confirm the changes and then a Confirm button. I built this using a Visualforce page and an Apex class shown below. The key method on the StandardSetController class for both the page table binding and in the updateCases method is getSelected.
NOTE: The 'recordSetVar' attribute on apex:page tells the platform this is a ListView page. This is very important for binding this page to your Custom Button. Though less important in the context of this demo as the variable it creates gives all records and not the selected ones.
NOTE: You can perform the update of the records in the 'bumpCases' method in one and effectively not provide the confirmation. However, be warned that this will likely raise a concern if your putting your code through Salesforce Security Review. As, rightly so, they see code updating the database as part of a page navigation a security risk.
Finally, you need to create your Custom Button under Customise > Cases > Buttons and Links and then use Customise > Cases > Search Layouts to add your button to the List View layout. This is what my button definition looks like.
Enjoy!