Update:

There is an issue with this method not allowing you to save the selection due to the pick list value not being in the entity.
This is caused by the jscript only updates the form not the entity data. This some limits your to working with the picklist text and not it's id value.

I added some script to the onload and onsave events to manage this. You'll need to create an additional text field to hold the value. I called mine new_promotionlist_text. This is a field on the form that is hidden by the script. It allows the picklist script to save the value of the list and then reset it when the list reloaded. 

=============================================

The purpose of a dynamic pick list is to allow you to make modifications to the list with as little impact as possible. Static list are effective for data that doesn't change often. For list values that need updating, a dynamic pick list is the trick. In addition, you could use the same technique to pull data from external systems and make available in the list.

The method I'll describe is pretty well known ( see www.stunnware.com as well). I thought it'd be good to revisit and put it up on the blog.

The method uses a custom entity to hold the values for the pick list and jscript to load the values into the picklist when the form loads.
The jscript will query the data using the CRM web services. You could just as easily call into other web services that return data from external systems or have the custom entity that holds the data get update externally as well.

I've created a sample that allows me to pull from a list of promotional events and show on the lead form

Here are the steps.

1. Create a custom entity to hold the values - Promotions, well use the name attribute to load in the list

2. Create a pick list on the lead form to hold the values , promotionlist

3. Add the jscript to the OnLoad form event.

DL3

Lead form with the dynamic pick list for promotions.

 

DL1

This is the custom entity Promotions, that hold the values to be put in the list.  You can update the values here and they will automatically show up
for other users in the list. By managing security on the Promotions entity, you can control who updates the list.
 

DL2

Make sure you enabled the Jscript in the lead form onload event after you put it in.

Below is the jscript you'll need to add.

Notes -
new_name is the attribute name that we want to pull from the promotion entity.
new_promotionlist is the pick list we will add values to.
You can remove the comments // on the alert messages to help with debugging.   // alert(msg);

// OnSave
crmForm.all.new_promotionlist_text.DataValue = crmForm.all.new_promotionlist.SelectedText;
crmForm.all.new_promotionlist.length = 0;


// OnLoad
crmForm.all.new_promotionlist_text.style.visibility = 'hidden';

var xml = "" +
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
GenerateAuthenticationHeader() +
" <soap:Body>" +
" <RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
" <query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
" <q1:EntityName>new_promotion</q1:EntityName>" +
" <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
" <q1:Attributes>" +
" <q1:Attribute>new_name</q1:Attribute>" +
" </q1:Attributes>" +
" </q1:ColumnSet>" +
" <q1:Distinct>false</q1:Distinct>" +
" </query>" +
" </RetrieveMultiple>" +
" </soap:Body>" +
"</soap:Envelope>" +
"";

var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");

xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);

// Capture the result.
var resultXml = xmlHttpRequest.responseXML;
//alert(resultXml.xml);

// Check for errors.
var errorCount = resultXml.selectNodes('//error').length;
if (errorCount != 0)
{
var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
//alert(msg);
}
// Parse and display the results.
else
{
var results = resultXml.getElementsByTagName('BusinessEntity');
var msg = "";
var pick = crmForm.all.new_promotionlist;  // List
if (results.length == 0)
{
  msg = "No records found";
// alert(msg);
  return;
}
else
{
  var entityNodes = resultXml.selectNodes("//RetrieveMultipleResult/BusinessEntities/BusinessEntity");

  // Loop through the collection of returned entities.
  for (var i = 0; i < entityNodes.length; i++)
  {
      var entityNode = entityNodes[i];
      var nameNode = entityNode.selectSingleNode("q1:new_name");
      var name = (nameNode == null) ? null : nameNode.text;
      pick.AddOption(name,i);
   }
}

crmForm.all.new_promotionlist.SelectedText = crmForm.all.new_promotionlist_text.DataValue;
}

-cheers
jonw