예제 #1
0
		private void OnDataBinding(object sender, EventArgs e)
		{
			Literal lbl = (Literal)sender;
			DataGridItem objContainer = (DataGridItem) lbl.NamingContainer;
			DataRowView row = objContainer.DataItem as DataRowView;
			if ( row != null )
			{
				// 04/30/2006   Use the Context to store pointers to the localization objects.
				// This is so that we don't need to require that the page inherits from SplendidPage. 
				L10N L10n = HttpContext.Current.Items["L10n"] as L10N;
				if ( L10n == null )
				{
					// 04/26/2006   We want to have the AccessView on the SystemCheck page. 
					L10n = new L10N(Sql.ToString(HttpContext.Current.Session["USER_SETTINGS/CULTURE"]));
				}
				if ( row[sDATA_FIELD] != DBNull.Value )
				{
					lbl.Text = L10n.Term(Sql.ToString(row[sDATA_FIELD]));
				}
			}
			else
			{
				lbl.Text = sDATA_FIELD;
			}
		}
예제 #2
0
파일: ACLGrid.cs 프로젝트: huamouse/Taoqi
		private void lit_OnDataBinding(object sender, EventArgs e)
		{
			Literal lbl = (Literal)sender;
			DataGridItem objContainer = (DataGridItem) lbl.NamingContainer;
			// 04/30/2006   Use the Context to store pointers to the localization objects.
			// This is so that we don't need to require that the page inherits from SplendidPage. 
			L10N L10n = HttpContext.Current.Items["L10n"] as L10N;
			if ( L10n == null )
			{
				// 04/26/2006   We want to have the AccessView on the SystemCheck page. 
				L10n = new L10N(Sql.ToString(HttpContext.Current.Session["USER_SETTINGS/CULTURE"]));
			}
			lbl.Text = L10n.Term(sLABEL);
		}
예제 #3
0
파일: Rest.svc.cs 프로젝트: huamouse/Taoqi
		public void DeleteModuleItem(string ModuleName, Guid ID)
		{
			HttpApplicationState Application = HttpContext.Current.Application;
			HttpRequest          Request     = HttpContext.Current.Request    ;
			
			if ( Sql.IsEmptyString(ModuleName) )
				throw(new Exception("The module name must be specified."));
			string sTABLE_NAME = Sql.ToString(Application["Modules." + ModuleName + ".TableName"]);
			if ( Sql.IsEmptyString(sTABLE_NAME) )
				throw(new Exception("Unknown module: " + ModuleName));
			// 08/22/2011   Add admin control to REST API. 
			int nACLACCESS = Security.GetUserAccess(ModuleName, "delete");
			if ( !Security.IsAuthenticated() || !Sql.ToBoolean(Application["Modules." + ModuleName + ".RestEnabled"]) || nACLACCESS < 0 )
			{
				L10N L10n = new L10N(Sql.ToString(HttpContext.Current.Session["USER_SETTINGS/CULTURE"]));
				throw(new Exception(L10n.Term("ACL.LBL_INSUFFICIENT_ACCESS")));
			}
			
			DeleteTableItem(sTABLE_NAME, ID);
		}
예제 #4
0
		// 03/07/2008   There is a better time to initialize the culture. 
		protected override void InitializeCulture()
		{
			// 08/30/2005   Move the L10N creation to this get function so that the first control 
			// that gets created will cause the creation of L10N.  The UserControls get the OnInit event before the Page onInit event. 
			// 03/07/2008   The page lifecycle has been designed to always call InitializeCulture before the page itself 
			// or any of its child controls have done any work with localized resources.
			m_sCULTURE     = Sql.ToString (Session["USER_SETTINGS/CULTURE"   ]);
			m_sDATEFORMAT  = Sql.ToString (Session["USER_SETTINGS/DATEFORMAT"]);
			m_sTIMEFORMAT  = Sql.ToString (Session["USER_SETTINGS/TIMEFORMAT"]);

			L10n = new L10N(m_sCULTURE);
			// 03/07/2008   We need to set the page culture so that the AJAX engine will initialize Sys.CultureInfo.CurrentCulture. 
			try
			{
				this.Culture = L10n.NAME;
			}
			catch
			{
				// 08/19/2013   An invalid default language can crash the app.  Always default to English. 
				// Don't log the error as it would be generated for every page request. 
				this.Culture = "en-US";
			}

			// 08/30/2005   Move the TimeZone creation to this get function so that the first control 
			// that gets created will cause the creation of TimeZone.  The UserControls get the OnInit event before the Page onInit event. 
			m_gTIMEZONE = Sql.ToGuid(Session["USER_SETTINGS/TIMEZONE"]);
			T10n = TimeZone.CreateTimeZone(m_gTIMEZONE);
			if ( T10n.ID != m_gTIMEZONE )
			{
				// 08/30/2005  If we are using a default, then update the session so that future controls will be quicker. 
				m_gTIMEZONE = T10n.ID ;
				Session["USER_SETTINGS/TIMEZONE"] = m_gTIMEZONE.ToString() ;
			}

			Guid gCURRENCY_ID = Sql.ToGuid(Session["USER_SETTINGS/CURRENCY"]);
			C10n = Currency.CreateCurrency(gCURRENCY_ID);
			if ( C10n.ID != gCURRENCY_ID )
			{
				// 05/09/2006  If we are using a default, then update the session so that future controls will be quicker. 
				gCURRENCY_ID = C10n.ID;
				Session["USER_SETTINGS/CURRENCY"] = gCURRENCY_ID.ToString();
				
			}
			// 08/05/2006   We cannot set the CurrencyDecimalSeparator directly on Mono as it is read-only.  
			// Hold off setting the CurrentCulture until we have updated all the settings. 
			CultureInfo culture = CultureInfo.CreateSpecificCulture(L10n.NAME);
			culture.DateTimeFormat.ShortDatePattern = m_sDATEFORMAT;
			culture.DateTimeFormat.ShortTimePattern = m_sTIMEFORMAT;
			// 05/29/2013   LongTimePattern is used in ListView. 
			culture.DateTimeFormat.LongTimePattern  = m_sTIMEFORMAT;

			// 03/30/2007   Always set the currency symbol.  It is not retained between page requests. 
			// 07/28/2006   We cannot set the CurrencySymbol directly on Mono as it is read-only.  
			// 03/07/2008   Move all localization to InitializeCulture(). 
			// Just clone the culture and modify the clone. 
			// CultureInfo culture = Thread.CurrentThread.CurrentCulture.Clone() as CultureInfo;
			culture.NumberFormat.CurrencySymbol   = C10n.SYMBOL;

			// 05/09/2006   Initialize the numeric separators. 
			// 03/07/2008   We are going to stop allowing the user to set the number separators. 
			// It does not work well when we allow the user to change the language using a drop-down. 
			// We are now using Microsoft AJAX localization, so there is no longer a need to manage the localization ourselves. 

			//string sGROUP_SEPARATOR   = Sql.ToString(Session["USER_SETTINGS/GROUP_SEPARATOR"  ]);
			//string sDECIMAL_SEPARATOR = Sql.ToString(Session["USER_SETTINGS/DECIMAL_SEPARATOR"]);
			// 06/03/2006   Setting the separators is causing some users a problem.  It may be because the strings were empty. 
			// 02/29/2008   The config value should only be used as an override.  We should default to the .NET culture value. 
			//if ( !Sql.IsEmptyString(sGROUP_SEPARATOR  ) ) culture.NumberFormat.CurrencyGroupSeparator   = sGROUP_SEPARATOR  ;
			//if ( !Sql.IsEmptyString(sDECIMAL_SEPARATOR) ) culture.NumberFormat.CurrencyDecimalSeparator = sDECIMAL_SEPARATOR;
			//if ( !Sql.IsEmptyString(sGROUP_SEPARATOR  ) ) culture.NumberFormat.NumberGroupSeparator     = sGROUP_SEPARATOR  ;
			//if ( !Sql.IsEmptyString(sDECIMAL_SEPARATOR) ) culture.NumberFormat.NumberDecimalSeparator   = sDECIMAL_SEPARATOR;

			// 08/30/2005  We don't need the long time pattern because we simply do not use it. 
			//Thread.CurrentThread.CurrentCulture.DateTimeFormat.LongTimePattern  = m_sTIMEFORMAT;
			//Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
			//08/05/2006   Apply the modified cultures. 
			Thread.CurrentThread.CurrentCulture   = culture;
			Thread.CurrentThread.CurrentUICulture = culture;
		}
예제 #5
0
파일: RulesUtil.cs 프로젝트: huamouse/Taoqi
		public SplendidReportThis(HttpApplicationState Application, L10N L10n, string sModule, DataRow Row)
		{
			this.Application       = Application;
			this.L10n              = L10n       ;
			this.Module            = sModule    ;
			this.Row               = Row        ;
			this.gASSIGNED_USER_ID = Guid.Empty ;
			if ( Row != null )
			{
				this.Table = Row.Table;
				if ( Table != null && Table.Columns.Contains("ASSIGNED_USER_ID") )
					gASSIGNED_USER_ID = Sql.ToGuid(Row["ASSIGNED_USER_ID"]);
			}
		}
예제 #6
0
파일: RulesUtil.cs 프로젝트: huamouse/Taoqi
		public SplendidWizardThis(L10N L10n, string sModule, DataRow Row)
		{
			this.L10n              = L10n      ;
			this.Row               = Row       ;
			this.Module            = sModule   ;
			this.gASSIGNED_USER_ID = Guid.Empty;
			if ( Row.Table != null && Row.Table.Columns.Contains("ASSIGNED_USER_ID") )
				gASSIGNED_USER_ID = Sql.ToGuid(Row["ASSIGNED_USER_ID"]);
		}
예제 #7
0
파일: RulesUtil.cs 프로젝트: huamouse/Taoqi
		public SplendidControlThis(SplendidControl Container, string sModule, DataRow Row)
		{
			this.Container = Container;
			this.Module    = sModule  ;
			this.Row       = Row      ;
			if ( Row != null )
				this.Table = Row.Table;
			this.L10n      = Container.GetL10n();
		}
예제 #8
0
		public static void AppendDetailViewFields(string sDETAIL_NAME, HtmlTable tbl, DataRow rdr, L10N L10n, TimeZone T10n, CommandEventHandler Page_Command)
		{
			if ( tbl == null )
			{
				SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "HtmlTable is not defined for " + sDETAIL_NAME);
				return;
			}
			DataTable dtFields = SplendidCache.DetailViewFields(sDETAIL_NAME);
			AppendDetailViewFields(dtFields.DefaultView, tbl, rdr, L10n, T10n, Page_Command, false);
		}
예제 #9
0
		// 05/26/2007   We need a way set the fields without creating the controls. 
		public static void SetEditViewFields(System.Web.UI.UserControl Parent, string sEDIT_NAME, IDataReader rdr, L10N L10n, TimeZone T10n)
		{
			// 01/01/2008   Pull config flag outside the loop. 
			bool bEnableTeamManagement  = Crm.Config.enable_team_management();
			DataTable dtFields = SplendidCache.EditViewFields(sEDIT_NAME);
			DataView dvFields  = dtFields.DefaultView;
			foreach(DataRowView row in dvFields)
			{
				string sFIELD_TYPE        = Sql.ToString (row["FIELD_TYPE"       ]);
				string sDATA_LABEL        = Sql.ToString (row["DATA_LABEL"       ]);
				string sDATA_FIELD        = Sql.ToString (row["DATA_FIELD"       ]);
				string sDISPLAY_FIELD     = Sql.ToString (row["DISPLAY_FIELD"    ]);
				// 11/02/2010   We need a way to insert NONE into the a ListBox while still allowing multiple rows. 
				// The trick will be to use a negative number.  Use an absolute value here to reduce the areas to fix. 
				int    nFORMAT_ROWS       = Math.Abs(Sql.ToInteger(row["FORMAT_ROWS"]));
				
				if ( sDATA_FIELD == "TEAM_ID" || sDATA_FIELD == "TEAM_SET_NAME" )
				{
					if ( !bEnableTeamManagement )
					{
						sFIELD_TYPE = "Blank";
					}
				}
				if ( String.Compare(sFIELD_TYPE, "Blank", true) == 0 )
				{
				}
				else if ( String.Compare(sFIELD_TYPE, "Label", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						Literal litField = Parent.FindControl(sDATA_FIELD) as Literal;
						if ( litField != null )
						{
							try
							{
								if ( sDATA_FIELD.IndexOf(".") >= 0 )
									litField.Text = L10n.Term(sDATA_FIELD);
								else
									litField.Text = Sql.ToString(rdr[sDATA_FIELD]);
							}
							catch(Exception ex)
							{
								SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								litField.Text = ex.Message;
							}
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "ListBox", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						try
						{
							if ( nFORMAT_ROWS > 0 )
							{
								// 12/02/2007   If format rows > 0 then this is a list box and not a drop down list. 
								ListBox lstField = Parent.FindControl(sDATA_FIELD) as ListBox;
								if ( lstField != null )
								{
									// 08/19/2010   Check the list before assigning the value. 
									Utils.SetValue(lstField, Sql.ToString(rdr[sDATA_FIELD]));
								}
							}
							else
							{
								DropDownList lstField = Parent.FindControl(sDATA_FIELD) as DropDownList;
								if ( lstField != null )
								{
									// 08/19/2010   Check the list before assigning the value. 
									Utils.SetValue(lstField, Sql.ToString(rdr[sDATA_FIELD]));
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
				// 06/16/2010   Add support for CheckBoxList. 
				else if ( String.Compare(sFIELD_TYPE, "CheckBoxList", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						try
						{
							CheckBoxList lstField = Parent.FindControl(sDATA_FIELD) as CheckBoxList;
							if ( lstField != null )
							{
								// 08/19/2010   Check the list before assigning the value. 
								Utils.SetValue(lstField, Sql.ToString(rdr[sDATA_FIELD]));
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
				// 06/16/2010   Add support for Radio buttons. 
				else if ( String.Compare(sFIELD_TYPE, "Radio", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						try
						{
							RadioButtonList lstField = Parent.FindControl(sDATA_FIELD) as RadioButtonList;
							if ( lstField != null )
							{
								// 08/19/2010   Check the list before assigning the value. 
								Utils.SetValue(lstField, Sql.ToString(rdr[sDATA_FIELD]));
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "CheckBox", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						try
						{
							CheckBox chkField = Parent.FindControl(sDATA_FIELD) as CheckBox;
							if ( chkField != null )
								chkField.Checked = Sql.ToBoolean(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "ChangeButton", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/04/2005   If the label is PARENT_TYPE, then change the label to a DropDownList.
						if ( sDATA_LABEL == "PARENT_TYPE" )
						{
							// 02/04/2011   We gave the PARENT_TYPE a unique name, but we need to update all EditViews and NewRecords. 
							DropDownList lstField = Parent.FindControl(sDATA_FIELD + "_PARENT_TYPE") as DropDownList;
							if ( lstField != null )
							{
								try
								{
									// 08/19/2010   Check the list before assigning the value. 
									Utils.SetValue(lstField, Sql.ToString(rdr[sDATA_LABEL]));
								}
								catch(Exception ex)
								{
									SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								}
							}
						}
						TextBox txtNAME = Parent.FindControl(sDISPLAY_FIELD) as TextBox;
						if ( txtNAME != null )
						{
							try
							{
								if ( !Sql.IsEmptyString(sDISPLAY_FIELD) )
									txtNAME.Text = Sql.ToString(rdr[sDISPLAY_FIELD]);
							}
							catch(Exception ex)
							{
								SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								txtNAME.Text = ex.Message;
							}
							HtmlInputHidden hidID = Parent.FindControl(sDATA_FIELD) as HtmlInputHidden;
							if ( hidID != null )
							{
								try
								{
									hidID.Value = Sql.ToString(rdr[sDATA_FIELD]);
								}
								catch(Exception ex)
								{
									SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
									txtNAME.Text = ex.Message;
								}
							}
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "ModulePopup", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						TextBox txtNAME = Parent.FindControl(sDISPLAY_FIELD) as TextBox;
						if ( txtNAME != null )
						{
							try
							{
								if ( !Sql.IsEmptyString(sDISPLAY_FIELD) )
									txtNAME.Text = Sql.ToString(rdr[sDISPLAY_FIELD]);
							}
							catch(Exception ex)
							{
								SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								txtNAME.Text = ex.Message;
							}
							HtmlInputHidden hidID = Parent.FindControl(sDATA_FIELD) as HtmlInputHidden;
							if ( hidID != null )
							{
								try
								{
									hidID.Value = Sql.ToString(rdr[sDATA_FIELD]);
								}
								catch(Exception ex)
								{
									SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
									txtNAME.Text = ex.Message;
								}
							}
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "TextBox", true) == 0 || String.Compare(sFIELD_TYPE, "Password", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						TextBox txtField = Parent.FindControl(sDATA_FIELD) as TextBox;
						if ( txtField != null )
						{
							try
							{
								int    nOrdinal  = rdr.GetOrdinal(sDATA_FIELD);
								string sTypeName = rdr.GetDataTypeName(nOrdinal);
								if ( sTypeName == "money" || rdr[sDATA_FIELD].GetType() == typeof(System.Decimal) )
									txtField.Text = Sql.ToDecimal(rdr[sDATA_FIELD]).ToString("#,##0.00");
								else
									txtField.Text = Sql.ToString(rdr[sDATA_FIELD]);
							}
							catch(Exception ex)
							{
								SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								txtField.Text = ex.Message;
							}
						}
					}
				}
				// 04/02/2009   Add support for FCKEditor to the EditView. 
				else if ( String.Compare(sFIELD_TYPE, "HtmlEditor", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 09/18/2011   Upgrade to CKEditor 3.6.2. 
						CKEditorControl txtField = Parent.FindControl(sDATA_FIELD) as CKEditorControl;
						if ( txtField != null )
						{
							try
							{
								txtField.Text = Sql.ToString(rdr[sDATA_FIELD]);
							}
							catch(Exception ex)
							{
								SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								txtField.Text = ex.Message;
							}
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "DatePicker", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						try
						{
						DatePicker ctlDate = Parent.FindControl(sDATA_FIELD) as DatePicker;
							if ( ctlDate != null )
								ctlDate.Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "DateTimePicker", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						try
						{
							DateTimePicker ctlDate = Parent.FindControl(sDATA_FIELD) as DateTimePicker;
							if ( ctlDate != null )
								ctlDate.Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "DateTimeEdit", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						try
						{
							DateTimeEdit ctlDate = Parent.FindControl(sDATA_FIELD) as DateTimeEdit;
							if ( ctlDate != null )
								ctlDate.Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
				// 06/20/2009   Add DateTimeNewRecord so that the NewRecord forms can use the Dynamic rendering. 
				else if ( String.Compare(sFIELD_TYPE, "DateTimeNewRecord", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						try
						{
							DateTimeEdit ctlDate = Parent.FindControl(sDATA_FIELD) as DateTimeEdit;
							if ( ctlDate != null )
								ctlDate.Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "File", true) == 0 )
				{
				}
				else if ( String.Compare(sFIELD_TYPE, "Image", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						try
						{
							HtmlInputHidden ctlHidden = Parent.FindControl(sDATA_FIELD) as HtmlInputHidden;
							Image imgField = Parent.FindControl("img" + sDATA_FIELD) as Image;
							if ( ctlHidden != null && imgField != null )
							{
								if ( !Sql.IsEmptyString(rdr[sDATA_FIELD]) )
								{
									ctlHidden.Value = Sql.ToString(rdr[sDATA_FIELD]);
									imgField.ImageUrl = "~/Images/Image.aspx?ID=" + ctlHidden.Value;
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
			}
		}
예제 #10
0
		// 11/12/2005   Not sure why, but Unified Search/Project List is not translating. 
		public void L10nTranslate()
		{
			if ( !bTranslated )
			{
				// 04/30/2006   Use the Context to store pointers to the localization objects.
				// This is so that we don't need to require that the page inherits from SplendidPage. 
				L10N L10n = HttpContext.Current.Items["L10n"] as L10N;
				if ( L10n == null )
				{
					// 04/26/2006   We want to have the AccessView on the SystemCheck page. 
					L10n = new L10N(Sql.ToString(HttpContext.Current.Session["USER_SETTINGS/CULTURE"]));
				}
				PagerStyle.PrevPageText = L10n.Term(PagerStyle.PrevPageText);
				PagerStyle.NextPageText = L10n.Term(PagerStyle.NextPageText);
				foreach(DataGridColumn col in Columns)
				{
					col.HeaderText = L10n.Term(col.HeaderText);
					// 02/25/2008   The main term may be used in the grid header. 
					// Instead of always requiring a separate list term, just remove the trailing colon. 
					if ( col.HeaderText.EndsWith(":") )
					{
						col.HeaderText = col.HeaderText.Substring(0, col.HeaderText.Length-1);
					}
				}
				bTranslated = true;
			}
		}
예제 #11
0
		private void OnDataBinding(object sender, EventArgs e)
		{
			Literal lbl = (Literal)sender;
			DataGridItem objContainer = (DataGridItem) lbl.NamingContainer;
			DataRowView row = objContainer.DataItem as DataRowView;
			if ( row != null )
			{
				// 04/30/2006   Use the Context to store pointers to the localization objects.
				// This is so that we don't need to require that the page inherits from SplendidPage. 
				L10N L10n = HttpContext.Current.Items["L10n"] as L10N;
				if ( L10n == null )
				{
					// 04/26/2006   We want to have the AccessView on the SystemCheck page. 
					L10n = new L10N(Sql.ToString(HttpContext.Current.Session["USER_SETTINGS/CULTURE"]));
				}
				if ( L10n != null )
				{
					if ( row[sDATA_FIELD] != DBNull.Value )
					{
						// 10/09/2010   Add PARENT_FIELD so that we can establish dependent listboxes. 
						if ( !Sql.IsEmptyString(sPARENT_FIELD) )
						{
							sLIST_NAME = Sql.ToString(row[sPARENT_FIELD]);
						}
						if ( !Sql.IsEmptyString(sLIST_NAME) )
						{
							string sList = sLIST_NAME;
							// 08/10/2008   Use an array to define the custom caches so that list is in the Cache module. 
							// This should reduce the number of times that we have to edit the SplendidDynamic module. 
							bool bCustomCache = false;
							lbl.Text = SplendidCache.CustomList(sLIST_NAME, Sql.ToString(row[sDATA_FIELD]), ref bCustomCache);
							if ( bCustomCache )
								return;
							// 01/18/2007   If AssignedUser list, then use the cached value to find the value. 
							if ( sLIST_NAME == "AssignedUser" )
							{
								lbl.Text = SplendidCache.AssignedUser(Sql.ToGuid(row[sDATA_FIELD]));
							}
							// 12/05/2005   The activity status needs to be dynamically converted to the correct list. 
							else if ( sLIST_NAME == "activity_status" )
							{
								string sACTIVITY_TYPE = String.Empty;
								try
								{
									sACTIVITY_TYPE = Sql.ToString(row["ACTIVITY_TYPE"]);
									switch ( sACTIVITY_TYPE )
									{
										case "Tasks"   :  sList = "task_status_dom"   ;  break;
										case "Meetings":  sList = "meeting_status_dom";  break;
										case "Calls"   :
											// 07/15/2006   Call status is translated externally. 
											lbl.Text = Sql.ToString(row[sDATA_FIELD]);
											return;
											//sList = "call_status_dom"   ;  break;
										case "Notes"   :
											// 07/15/2006   Note Status is not normally as it does not have a status. 
											lbl.Text = L10n.Term(".activity_dom.Note");
											return;
										// 06/15/2006   This list name for email_status does not follow the standard. 
										case "Emails"  :  sList = "dom_email_status"  ;  break;
										// 09/26/2013   Add Sms Messages status. 
										case "SmsMessages":  sList = "dom_sms_status"  ;  break;
										// 04/21/2006   If the activity does not have a status (such as a Note), then use activity_dom. 
										default        :  sList = "activity_dom"      ;  break;
									}
								}
								catch(Exception ex)
								{
									SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								}
								lbl.Text = Sql.ToString(L10n.Term("." + sList + ".", row[sDATA_FIELD]));
							}
							// 02/12/2008   If the list contains XML, then treat as a multi-selection. 
							else if ( Sql.ToString(row[sDATA_FIELD]).StartsWith("<?xml") )
							{
								StringBuilder sb = new StringBuilder();
								XmlDocument xml = new XmlDocument();
								xml.LoadXml(Sql.ToString(row[sDATA_FIELD]));
								XmlNodeList nlValues = xml.DocumentElement.SelectNodes("Value");
								foreach ( XmlNode xValue in nlValues )
								{
									if ( sb.Length > 0 )
										sb.Append(", ");
									sb.Append(L10n.Term("." + sLIST_NAME + ".", xValue.InnerText));
								}
								lbl.Text = sb.ToString();
							}
							else
							{
								lbl.Text = Sql.ToString(L10n.Term("." + sList + ".", row[sDATA_FIELD]));
							}
						}
					}
				}
				else
				{
					lbl.Text = Sql.ToString(row[sDATA_FIELD]);
				}
			}
			else
			{
				lbl.Text = sDATA_FIELD;
			}
		}
예제 #12
0
		public User USERS_USER_NAME_Get(string sNAME)
		{
			User item = new User();
			//try
			{
				if ( !Security.IsAuthenticated() )
					throw(new Exception("Authentication required"));

				Taoqi.DbProviderFactory dbf = Taoqi.DbProviderFactories.GetFactory();
				using ( IDbConnection con = dbf.CreateConnection() )
				{
					con.Open();
					using ( IDbCommand cmd = con.CreateCommand() )
					{
						bool bTeamFilter = !Security.isAdmin && Crm.Config.enable_team_management();
						if ( bTeamFilter )
						{
							cmd.CommandText = "select ID                      " + ControlChars.CrLf
							                + "     , USER_NAME               " + ControlChars.CrLf
							                + "  from vwTEAMS_ASSIGNED_TO_List" + ControlChars.CrLf
							                + " where MEMBERSHIP_USER_ID = @MEMBERSHIP_USER_ID" + ControlChars.CrLf;
							Sql.AddParameter(cmd, "@MEMBERSHIP_USER_ID", Security.USER_ID);
						}
						else
						{
							cmd.CommandText = "select ID                      " + ControlChars.CrLf
							                + "     , USER_NAME               " + ControlChars.CrLf
							                + "  from vwUSERS_ASSIGNED_TO_List" + ControlChars.CrLf
							                + " where 1 = 1                   " + ControlChars.CrLf;
						}
						// 07/12/2010   Allow fuzzy searching during AutoComplete. 
						Sql.AppendParameter(cmd, sNAME, (Sql.ToBoolean(Application["CONFIG.AutoComplete.Contains"]) ? Sql.SqlFilterMode.Contains : Sql.SqlFilterMode.StartsWith), "USER_NAME");
						// 07/02/2007   Sort is important so that the first match is selected. 
						cmd.CommandText += " order by USER_NAME" + ControlChars.CrLf;
						using ( IDataReader rdr = cmd.ExecuteReader(CommandBehavior.SingleRow) )
						{
							if ( rdr.Read() )
							{
								item.ID   = Sql.ToGuid   (rdr["ID"       ]);
								item.NAME = Sql.ToString (rdr["USER_NAME"]);
							}
						}
					}
				}
				if ( Sql.IsEmptyGuid(item.ID) )
				{
					string sCULTURE = Sql.ToString (Session["USER_SETTINGS/CULTURE"]);
					L10N L10n = new L10N(sCULTURE);
					throw(new Exception(L10n.Term("Users.ERR_USER_NOT_FOUND")));
				}
			}
			//catch
			{
				// 02/04/2007   Don't catch the exception.  
				// It is a web service, so the exception will be handled properly by the AJAX framework. 
			}
			return item;
		}
예제 #13
0
파일: Rest.svc.cs 프로젝트: huamouse/Taoqi
		public Guid Login(string UserName, string Password, string Version)
		{
			HttpApplicationState Application = HttpContext.Current.Application;
			HttpSessionState     Session     = HttpContext.Current.Session    ;
			HttpRequest          Request     = HttpContext.Current.Request    ;
			
			string sUSER_NAME   = UserName;
			string sPASSWORD    = Password;
			string sVERSION     = Version ;
			Guid gUSER_ID       = Guid.Empty;
			Guid gUSER_LOGIN_ID = Guid.Empty;
			
			// 02/23/2011   SYNC service should check for lockout. 
            //if ( SplendidInit.LoginFailures(Application, sUSER_NAME) >= Crm.Password.LoginLockoutCount(Application) )
            //{
            //    L10N L10n = new L10N("en-US");
            //    throw(new Exception(L10n.Term("Users.ERR_USER_LOCKED_OUT")));
            //}
			// 04/16/2013   Allow system to be restricted by IP Address. 
			if ( SplendidInit.InvalidIPAddress(Application, Request.UserHostAddress) )
			{
				L10N L10n = new L10N("en-US");
				throw(new Exception(L10n.Term("Users.ERR_INVALID_IP_ADDRESS")));
			}
			DbProviderFactory dbf = DbProviderFactories.GetFactory();
			using ( IDbConnection con = dbf.CreateConnection() )
			{
				con.Open();
				string sSQL;
				sSQL = "select ID                    " + ControlChars.CrLf
				     + "     , USER_NAME             " + ControlChars.CrLf
				     + "     , FULL_NAME             " + ControlChars.CrLf
				     + "     , IS_ADMIN              " + ControlChars.CrLf
				     + "     , STATUS                " + ControlChars.CrLf
				     + "     , PORTAL_ONLY           " + ControlChars.CrLf
				     + "     , TEAM_ID               " + ControlChars.CrLf
				     + "     , TEAM_NAME             " + ControlChars.CrLf
				     + "  from vwUSERS_Login         " + ControlChars.CrLf
				     + " where USER_NAME = @USER_NAME" + ControlChars.CrLf
				     + "   and USER_HASH = @USER_HASH" + ControlChars.CrLf;
				using ( IDbCommand cmd = con.CreateCommand() )
				{
					cmd.CommandText = sSQL;
					string sUSER_HASH = Security.HashPassword(sPASSWORD);
					// 12/25/2009   Use lowercase username to match the primary authentication function. 
					Sql.AddParameter(cmd, "@USER_NAME", sUSER_NAME.ToLower());
					Sql.AddParameter(cmd, "@USER_HASH", sUSER_HASH);
					using ( DbDataAdapter da = dbf.CreateDataAdapter() )
					{
						((IDbDataAdapter)da).SelectCommand = cmd;
						using ( DataTable dt = new DataTable() )
						{
							da.Fill(dt);
							if ( dt.Rows.Count > 0 )
							{
								DataRow row = dt.Rows[0];
								Security.USER_ID     = Sql.ToGuid   (row["ID"         ]);
								Security.USER_NAME   = Sql.ToString (row["USER_NAME"  ]);
								Security.FULL_NAME   = Sql.ToString (row["FULL_NAME"  ]);
								Security.isAdmin    = Sql.ToBoolean(row["IS_ADMIN"   ]);
								Security.PORTAL_ONLY = Sql.ToBoolean(row["PORTAL_ONLY"]);
								Security.TEAM_ID     = Sql.ToGuid   (row["TEAM_ID"    ]);
								Security.TEAM_NAME   = Sql.ToString (row["TEAM_NAME"  ]);
								gUSER_ID = Sql.ToGuid(row["ID"]);

								SplendidInit.LoadUserPreferences(gUSER_ID, String.Empty, String.Empty);
								SplendidInit.LoadUserACL(gUSER_ID);
								
								SqlProcs.spUSERS_LOGINS_InsertOnly(ref gUSER_LOGIN_ID, gUSER_ID, sUSER_NAME, "Anonymous", "Succeeded", Session.SessionID, Request.UserHostName, Request.Url.Host, Request.Path, Request.AppRelativeCurrentExecutionFilePath, Request.UserAgent);
								Security.USER_LOGIN_ID = gUSER_LOGIN_ID;
								// 02/20/2011   Log the success so that we can lockout the user. 
								SplendidInit.LoginTracking(Application, sUSER_NAME, true);
								SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "SyncUser login for " + sUSER_NAME);
							}
							else
							{
								SqlProcs.spUSERS_LOGINS_InsertOnly(ref gUSER_LOGIN_ID, Guid.Empty, sUSER_NAME, "Anonymous", "Failed", Session.SessionID, Request.UserHostName, Request.Url.Host, Request.Path, Request.AppRelativeCurrentExecutionFilePath, Request.UserAgent);
								// 02/20/2011   Log the failure so that we can lockout the user. 
								SplendidInit.LoginTracking(Application, sUSER_NAME, false);
								SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "SECURITY: failed attempted login for " + sUSER_NAME + " using Sync api");
							}
						}
					}
				}
			}
			if ( gUSER_ID == Guid.Empty )
			{
				SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "Invalid username and/or password for " + sUSER_NAME);
				throw(new Exception("Invalid username and/or password for " + sUSER_NAME));
			}
			return gUSER_ID;
		}
예제 #14
0
파일: Rest.svc.cs 프로젝트: huamouse/Taoqi
		private void DeleteRelatedItem(string sTABLE_NAME, string sRELATIONSHIP_TABLE, string sMODULE_FIELD_NAME, Guid gID, string sRELATED_FIELD_NAME, Guid gRELATED_ID)
		{
			HttpSessionState     Session     = HttpContext.Current.Session    ;
			try
			{
				if ( Security.IsAuthenticated() )
				{
					string sCULTURE = Sql.ToString (Session["USER_SETTINGS/CULTURE"]);
					L10N   L10n     = new L10N(sCULTURE);
					Regex  r        = new Regex(@"[^A-Za-z0-9_]");
					sTABLE_NAME = r.Replace(sTABLE_NAME, "").ToUpper();
					
					DbProviderFactory dbf = DbProviderFactories.GetFactory();
					using ( IDbConnection con = dbf.CreateConnection() )
					{
						con.Open();
						// 06/03/2011   Cache the Rest Table data. 
						// 11/26/2009   System tables cannot be updated. 
						// 06/04/2011   For relationships, we first need to check the access rights of the parent record. 
						using ( DataTable dtSYNC_TABLES = SplendidCache.RestTables(sTABLE_NAME, true) )
						{
							string sSQL;
							if ( dtSYNC_TABLES != null && dtSYNC_TABLES.Rows.Count > 0 )
							{
								DataRow rowSYNC_TABLE = dtSYNC_TABLES.Rows[0];
								string sMODULE_NAME = Sql.ToString (rowSYNC_TABLE["MODULE_NAME"]);
								string sVIEW_NAME   = Sql.ToString (rowSYNC_TABLE["VIEW_NAME"  ]);
								if ( Sql.IsEmptyString(sMODULE_NAME) )
								{
									throw(new Exception("sMODULE_NAME should not be empty for table " + sTABLE_NAME));
								}
								
								int nACLACCESS = Taoqi.Security.GetUserAccess(sMODULE_NAME, "edit");
								// 11/11/2009   First check if the user has access to this module. 
								if ( nACLACCESS >= 0 )
								{
									bool      bRecordExists              = false;
									bool      bAccessAllowed             = false;
									Guid      gLOCAL_ASSIGNED_USER_ID    = Guid.Empty;
									DataRow   rowCurrent                 = null;
									DataTable dtCurrent                  = new DataTable();
									sSQL = "select *"              + ControlChars.CrLf
									     + "  from " + sTABLE_NAME + ControlChars.CrLf
									     + " where DELETED = 0"    + ControlChars.CrLf;
									using ( IDbCommand cmd = con.CreateCommand() )
									{
										cmd.CommandText = sSQL;
										Sql.AppendParameter(cmd, gID, "ID");
										using ( DbDataAdapter da = dbf.CreateDataAdapter() )
										{
											((IDbDataAdapter)da).SelectCommand = cmd;
											// 11/27/2009   It may be useful to log the SQL during errors at this location. 
											try
											{
												da.Fill(dtCurrent);
											}
											catch
											{
												SplendidError.SystemError(new StackTrace(true).GetFrame(0), Sql.ExpandParameters(cmd));
												throw;
											}
											if ( dtCurrent.Rows.Count > 0 )
											{
												rowCurrent = dtCurrent.Rows[0];
												bRecordExists = true;
												// 01/18/2010   Apply ACL Field Security. 
												if ( dtCurrent.Columns.Contains("ASSIGNED_USER_ID") )
												{
													gLOCAL_ASSIGNED_USER_ID = Sql.ToGuid(rowCurrent["ASSIGNED_USER_ID"]);
												}
											}
										}
									}
									// 06/04/2011   We are not ready to handle conflicts. 
									//if ( !bConflicted )
									{
										if ( bRecordExists )
										{
											sSQL = "select count(*)"       + ControlChars.CrLf
											     + "  from " + sTABLE_NAME + ControlChars.CrLf;
											using ( IDbCommand cmd = con.CreateCommand() )
											{
												cmd.CommandText = sSQL;
												Security.Filter(cmd, sMODULE_NAME, "delete");
												Sql.AppendParameter(cmd, gID, "ID");
												try
												{
													if ( Sql.ToInteger(cmd.ExecuteScalar()) > 0 )
													{
														if ( (nACLACCESS > ACL_ACCESS.OWNER) || (nACLACCESS == ACL_ACCESS.OWNER && Security.USER_ID == gLOCAL_ASSIGNED_USER_ID) || !dtCurrent.Columns.Contains("ASSIGNED_USER_ID") )
															bAccessAllowed = true;
													}
												}
												catch
												{
													SplendidError.SystemError(new StackTrace(true).GetFrame(0), Sql.ExpandParameters(cmd));
													throw;
												}
											}
										}
										if ( bAccessAllowed )
										{
											// 11/24/2012   We do not need to check for RestTable access as that step was already done. 
											IDbCommand cmdDelete = SqlProcs.Factory(con, "sp" + sRELATIONSHIP_TABLE + "_Delete");
											using ( IDbTransaction trn = Sql.BeginTransaction(con) )
											{
												try
												{
													cmdDelete.Transaction = trn;
													foreach(IDbDataParameter par in cmdDelete.Parameters)
													{
														string sParameterName = Sql.ExtractDbName(cmdDelete, par.ParameterName).ToUpper();
														if ( sParameterName == sMODULE_FIELD_NAME )
															par.Value = gID;
														else if ( sParameterName == sRELATED_FIELD_NAME )
															par.Value = gRELATED_ID;
														else if ( sParameterName == "MODIFIED_USER_ID" )
															par.Value = Sql.ToDBGuid(Security.USER_ID);
														else
															par.Value = DBNull.Value;
													}
													cmdDelete.ExecuteScalar();
													trn.Commit();
												}
												catch
												{
													trn.Rollback();
													throw;
												}
											}
										}
										else
										{
											throw(new Exception(L10n.Term("ACL.LBL_NO_ACCESS")));
										}
									}
								}
								else
								{
									throw(new Exception(L10n.Term("ACL.LBL_NO_ACCESS")));
								}
							}
						}
					}
				}
			}
			catch(Exception ex)
			{
				SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);
				throw;
			}
		}
예제 #15
0
파일: Rest.svc.cs 프로젝트: huamouse/Taoqi
		public void DeleteRelatedItem(string ModuleName, Guid ID, string RelatedModule, Guid RelatedID)
		{
			HttpApplicationState Application = HttpContext.Current.Application;
			HttpRequest          Request     = HttpContext.Current.Request    ;
			
			if ( Sql.IsEmptyString(ModuleName) )
				throw(new Exception("The module name must be specified."));
			string sTABLE_NAME = Sql.ToString(Application["Modules." + ModuleName + ".TableName"]);
			if ( Sql.IsEmptyString(sTABLE_NAME) )
				throw(new Exception("Unknown module: " + ModuleName));
			// 08/22/2011   Add admin control to REST API. 
			int nACLACCESS = Security.GetUserAccess(ModuleName, "edit");
			if ( !Security.IsAuthenticated() || !Sql.ToBoolean(Application["Modules." + ModuleName + ".RestEnabled"]) || nACLACCESS < 0 )
			{
				L10N L10n = new L10N(Sql.ToString(HttpContext.Current.Session["USER_SETTINGS/CULTURE"]));
				throw(new Exception(L10n.Term("ACL.LBL_INSUFFICIENT_ACCESS")));
			}
			
			if ( Sql.IsEmptyString(RelatedModule) )
				throw(new Exception("The related module name must be specified."));
			string sRELATED_TABLE = Sql.ToString(Application["Modules." + RelatedModule + ".TableName"]);
			if ( Sql.IsEmptyString(sRELATED_TABLE) )
				throw(new Exception("Unknown module: " + RelatedModule));
			// 08/22/2011   Add admin control to REST API. 
			nACLACCESS = Security.GetUserAccess(RelatedModule, "edit");
			if ( !Security.IsAuthenticated() || !Sql.ToBoolean(Application["Modules." + RelatedModule + ".RestEnabled"]) || nACLACCESS < 0 )
			{
				L10N L10n = new L10N(Sql.ToString(HttpContext.Current.Session["USER_SETTINGS/CULTURE"]));
				throw(new Exception(L10n.Term("ACL.LBL_INSUFFICIENT_ACCESS")));
			}

			string sRELATIONSHIP_TABLE = sTABLE_NAME + "_" + sRELATED_TABLE;
			string sMODULE_FIELD_NAME  = Crm.Modules.SingularTableName(sTABLE_NAME   ) + "_ID";
			string sRELATED_FIELD_NAME = Crm.Modules.SingularTableName(sRELATED_TABLE) + "_ID";
			// 11/24/2012   In the special cases of Accounts Related and Contacts Reports To, we need to correct the field name. 
			if ( sMODULE_FIELD_NAME == "ACCOUNT_ID" && sRELATED_FIELD_NAME == "ACCOUNT_ID" )
			{
				sRELATIONSHIP_TABLE = "ACCOUNTS_MEMBERS";
				sRELATED_FIELD_NAME = "PARENT_ID";
			}
			else if ( sMODULE_FIELD_NAME == "CONTACT_ID" && sRELATED_FIELD_NAME == "CONTACT_ID" )
			{
				sRELATIONSHIP_TABLE = "CONTACTS_DIRECT_REPORTS";
				sRELATED_FIELD_NAME = "REPORTS_TO_ID";
			}
			
			DataTable dtSYNC_TABLES = SplendidCache.RestTables("vw" + sRELATIONSHIP_TABLE, true);
			if ( dtSYNC_TABLES != null && dtSYNC_TABLES.Rows.Count == 0 )
			{
				sRELATIONSHIP_TABLE = sRELATED_TABLE + "_" + sTABLE_NAME;
				dtSYNC_TABLES = SplendidCache.RestTables("vw" + sRELATIONSHIP_TABLE, true);
				if ( dtSYNC_TABLES != null && dtSYNC_TABLES.Rows.Count == 0 )
				{
					L10N L10n = new L10N(Sql.ToString(HttpContext.Current.Session["USER_SETTINGS/CULTURE"]));
					throw(new Exception(L10n.Term("ACL.LBL_INSUFFICIENT_ACCESS") + " to relationship between modules " + ModuleName + " and " + RelatedModule));
				}
			}
			DeleteRelatedItem(sTABLE_NAME, sRELATIONSHIP_TABLE, sMODULE_FIELD_NAME, ID, sRELATED_FIELD_NAME, RelatedID);
		}
예제 #16
0
		public static void AppendEditViewFields(DataView dvFields, HtmlTable tbl, DataRow rdr, L10N L10n, TimeZone T10n, CommandEventHandler Page_Command, bool bLayoutMode, string sSubmitClientID)
		{
			bool bIsMobile = false;
			SplendidPage Page = tbl.Page as SplendidPage;
			if ( Page != null )
				bIsMobile = Page.IsMobile;
			// 06/21/2009   We need the script manager to properly register EnterKey presses for text boxes. 
			ScriptManager mgrAjax = ScriptManager.GetCurrent(tbl.Page);
			// 11/23/2009   Taoqi 4.0 is very slow on Blackberry devices.  Lets try and turn off AJAX AutoComplete. 
			bool bAjaxAutoComplete = (mgrAjax != null);
			// 12/07/2009   The Opera Mini browser does not support popups. Use a DropdownList instead. 
			bool bSupportsPopups = true;
			if ( bIsMobile )
			{
				// 11/24/2010   .NET 4 has broken the compatibility of the browser file system. 
				// We are going to minimize our reliance on browser files in order to reduce deployment issues. 
				bAjaxAutoComplete = Utils.AllowAutoComplete && (mgrAjax != null);
				bSupportsPopups = Utils.SupportsPopups;
			}
			// 07/28/2010   Save AjaxAutoComplete and SupportsPopups for use in TeamSelect and KBSelect. 
			// We are having issues with the data binding event occurring before the page load. 
			Page.Items["AjaxAutoComplete"] = bAjaxAutoComplete;
			Page.Items["SupportsPopups"  ] = bSupportsPopups  ;
			// 05/06/2010   Use a special Page flag to override the default IsPostBack behavior. 
			bool bIsPostBack = tbl.Page.IsPostBack;
			bool bNotPostBack = false;
			if ( tbl.TemplateControl is SplendidControl )
			{
				bNotPostBack = (tbl.TemplateControl as SplendidControl).NotPostBack;
				bIsPostBack = tbl.Page.IsPostBack && !bNotPostBack;
			}

			HtmlTableRow tr = null;
			// 11/28/2005   Start row index using the existing count so that headers can be specified. 
			int nRowIndex = tbl.Rows.Count - 1;
			int nColIndex = 0;
			HtmlTableCell tdLabel = null;
			HtmlTableCell tdField = null;
			// 01/07/2006   Show table borders in layout mode. This will help distinguish blank lines from wrapped lines. 
			if ( bLayoutMode )
				tbl.Border = 1;
			// 11/15/2007   If there are no fields in the detail view, then hide the entire table. 
			// This allows us to hide the table by removing all detail view fields. 
			// 09/12/2009   There is no reason to hide the table when in layout mode. 
			if ( dvFields.Count == 0 && tbl.Rows.Count <= 1 && !bLayoutMode )
				tbl.Visible = false;

			// 01/27/2008   We need the schema table to determine if the data label is free-form text. 
			// 03/21/2008   We need to use a view to search for the rows for the ColumnName. 
			// 01/18/2010   To apply ACL Field Security, we need to know if the current record has an ASSIGNED_USER_ID field, and its value. 
			Guid gASSIGNED_USER_ID = Guid.Empty;
			//DataView vwSchema = null;
			if ( rdr != null )
			{
				// 11/22/2010   Convert data reader to data table for Rules Wizard. 
				//vwSchema = new DataView(rdr.GetSchemaTable());
				//vwSchema.RowFilter = "ColumnName = 'ASSIGNED_USER_ID'";
				//if ( vwSchema.Count > 0 )
				if ( rdr.Table.Columns.Contains("ASSIGNED_USER_ID") )
				{
					gASSIGNED_USER_ID = Sql.ToGuid(rdr["ASSIGNED_USER_ID"]);
				}
			}

			// 01/01/2008   Pull config flag outside the loop. 
			bool bEnableTeamManagement  = Crm.Config.enable_team_management();
			bool bRequireTeamManagement = Crm.Config.require_team_management();
			// 01/01/2008   We need a quick way to require user assignments across the system. 
			bool bRequireUserAssignment = Crm.Config.require_user_assignment();
			// 08/28/2009   Allow dynamic teams to be turned off. 
			bool bEnableDynamicTeams   = Crm.Config.enable_dynamic_teams();
			HttpSessionState Session = HttpContext.Current.Session;
			HttpApplicationState Application = HttpContext.Current.Application;
			// 10/07/2010   Convert the currency values before displaying. 
			// The UI culture should already be set to format the currency. 
			Currency C10n = HttpContext.Current.Items["C10n"] as Currency;
			// 05/08/2010   Define the copy buttons outside the loop so that we can replace the javascript with embedded code. 
			// This is so that the javascript will run properly in the SixToolbar UpdatePanel. 
			HtmlInputButton btnCopyRight = null;
			HtmlInputButton btnCopyLeft  = null;
			// 09/13/2010   We need to prevent duplicate names. 
			Hashtable hashLABEL_IDs = new Hashtable();
			bool bSupportsDraggable = Sql.ToBoolean(Session["SupportsDraggable"]);
			// 12/13/2013   Allow each line item to have a separate tax rate. 
			bool bEnableTaxLineItems = Sql.ToBoolean(HttpContext.Current.Application["CONFIG.Orders.TaxLineItems"]);
			foreach(DataRowView row in dvFields)
			{
				string sEDIT_NAME         = Sql.ToString (row["EDIT_NAME"        ]);
				int    nFIELD_INDEX       = Sql.ToInteger(row["FIELD_INDEX"      ]);
				string sFIELD_TYPE        = Sql.ToString (row["FIELD_TYPE"       ]);
				string sDATA_LABEL        = Sql.ToString (row["DATA_LABEL"       ]);
				string sDATA_FIELD        = Sql.ToString (row["DATA_FIELD"       ]);
				// 01/19/2010   We need to be able to format a Float field to prevent too many decimal places. 
				string sDATA_FORMAT       = Sql.ToString (row["DATA_FORMAT"      ]);
				string sDISPLAY_FIELD     = Sql.ToString (row["DISPLAY_FIELD"    ]);
				string sCACHE_NAME        = Sql.ToString (row["CACHE_NAME"       ]);
				bool   bDATA_REQUIRED     = Sql.ToBoolean(row["DATA_REQUIRED"    ]);
				bool   bUI_REQUIRED       = Sql.ToBoolean(row["UI_REQUIRED"      ]);
				string sONCLICK_SCRIPT    = Sql.ToString (row["ONCLICK_SCRIPT"   ]);
				string sFORMAT_SCRIPT     = Sql.ToString (row["FORMAT_SCRIPT"    ]);
				short  nFORMAT_TAB_INDEX  = Sql.ToShort  (row["FORMAT_TAB_INDEX" ]);
				int    nFORMAT_MAX_LENGTH = Sql.ToInteger(row["FORMAT_MAX_LENGTH"]);
				int    nFORMAT_SIZE       = Sql.ToInteger(row["FORMAT_SIZE"      ]);
				// 11/02/2010   We need a way to insert NONE into the a ListBox while still allowing multiple rows. 
				// The trick will be to use a negative number.  Use an absolute value here to reduce the areas to fix. 
				int    nFORMAT_ROWS       = Math.Abs(Sql.ToInteger(row["FORMAT_ROWS"]));
				int    nFORMAT_COLUMNS    = Sql.ToInteger(row["FORMAT_COLUMNS"   ]);
				int    nCOLSPAN           = Sql.ToInteger(row["COLSPAN"          ]);
				int    nROWSPAN           = Sql.ToInteger(row["ROWSPAN"          ]);
				string sLABEL_WIDTH       = Sql.ToString (row["LABEL_WIDTH"      ]);
				string sFIELD_WIDTH       = Sql.ToString (row["FIELD_WIDTH"      ]);
				int    nDATA_COLUMNS      = Sql.ToInteger(row["DATA_COLUMNS"     ]);
				// 05/17/2009   Add support for a generic module popup. 
				string sMODULE_TYPE       = String.Empty;
				try
				{
					sMODULE_TYPE = Sql.ToString (row["MODULE_TYPE"]);
				}
				catch(Exception ex)
				{
					// 05/17/2009   The MODULE_TYPE is not in the view, then log the error and continue. 
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
				}
				// 09/13/2010   Add relationship fields. 
				bool   bVALID_RELATED                = false;
				string sRELATED_SOURCE_MODULE_NAME   = String.Empty;
				string sRELATED_SOURCE_VIEW_NAME     = String.Empty;
				string sRELATED_SOURCE_ID_FIELD      = String.Empty;
				string sRELATED_SOURCE_NAME_FIELD    = String.Empty;
				string sRELATED_VIEW_NAME            = String.Empty;
				string sRELATED_ID_FIELD             = String.Empty;
				string sRELATED_NAME_FIELD           = String.Empty;
				string sRELATED_JOIN_FIELD           = String.Empty;
				try
				{
					sRELATED_SOURCE_MODULE_NAME   = Sql.ToString (row["RELATED_SOURCE_MODULE_NAME"  ]);
					sRELATED_SOURCE_VIEW_NAME     = Sql.ToString (row["RELATED_SOURCE_VIEW_NAME"    ]);
					sRELATED_SOURCE_ID_FIELD      = Sql.ToString (row["RELATED_SOURCE_ID_FIELD"     ]);
					sRELATED_SOURCE_NAME_FIELD    = Sql.ToString (row["RELATED_SOURCE_NAME_FIELD"   ]);
					sRELATED_VIEW_NAME            = Sql.ToString (row["RELATED_VIEW_NAME"           ]);
					sRELATED_ID_FIELD             = Sql.ToString (row["RELATED_ID_FIELD"            ]);
					sRELATED_NAME_FIELD           = Sql.ToString (row["RELATED_NAME_FIELD"          ]);
					sRELATED_JOIN_FIELD           = Sql.ToString (row["RELATED_JOIN_FIELD"          ]);
					bVALID_RELATED =  !Sql.IsEmptyString(sRELATED_SOURCE_VIEW_NAME) && !Sql.IsEmptyString(sRELATED_SOURCE_ID_FIELD) && !Sql.IsEmptyString(sRELATED_SOURCE_NAME_FIELD) 
					               && !Sql.IsEmptyString(sRELATED_VIEW_NAME       ) && !Sql.IsEmptyString(sRELATED_ID_FIELD       ) && !Sql.IsEmptyString(sRELATED_NAME_FIELD       ) 
					               && !Sql.IsEmptyString(sRELATED_JOIN_FIELD      );
				}
				catch(Exception ex)
				{
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
				}
				// 10/09/2010   Add PARENT_FIELD so that we can establish dependent listboxes. 
				string sPARENT_FIELD = String.Empty;
				try
				{
					sPARENT_FIELD = Sql.ToString (row["PARENT_FIELD"]);
				}
				catch(Exception ex)
				{
					// 05/17/2009   The PARENT_FIELD is not in the view, then log the error and continue. 
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
				}

				// 04/02/2008   Add support for Regular Expression validation. 
				string sFIELD_VALIDATOR_MESSAGE = Sql.ToString (row["FIELD_VALIDATOR_MESSAGE"]);
				string sVALIDATION_TYPE         = Sql.ToString (row["VALIDATION_TYPE"        ]);
				string sREGULAR_EXPRESSION      = Sql.ToString (row["REGULAR_EXPRESSION"     ]);
				string sDATA_TYPE               = Sql.ToString (row["DATA_TYPE"              ]);
				string sMININUM_VALUE           = Sql.ToString (row["MININUM_VALUE"          ]);
				string sMAXIMUM_VALUE           = Sql.ToString (row["MAXIMUM_VALUE"          ]);
				string sCOMPARE_OPERATOR        = Sql.ToString (row["COMPARE_OPERATOR"       ]);
				// 06/12/2009   Add TOOL_TIP for help hover.
				string sTOOL_TIP                = String.Empty;
				try
				{
					sTOOL_TIP = Sql.ToString (row["TOOL_TIP"]);
				}
				catch(Exception ex)
				{
					// 06/12/2009   The TOOL_TIP is not in the view, then log the error and continue. 
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
				}
				
				// 12/02/2007   Each view can now have its own number of data columns. 
				// This was needed so that search forms can have 4 data columns. The default is 2 columns. 
				if ( nDATA_COLUMNS == 0 )
					nDATA_COLUMNS = 2;

				// 01/18/2010   To apply ACL Field Security, we need to know if the Module Name, which we will extract from the EditView Name. 
				string sMODULE_NAME = String.Empty;
				string[] arrEDIT_NAME = sEDIT_NAME.Split('.');
				if ( arrEDIT_NAME.Length > 0 )
					sMODULE_NAME = arrEDIT_NAME[0];
				bool bIsReadable  = true;
				bool bIsWriteable = true;
				if ( SplendidInit.bEnableACLFieldSecurity )
				{
					Security.ACL_FIELD_ACCESS acl = Security.GetUserFieldSecurity(sMODULE_NAME, sDATA_FIELD, gASSIGNED_USER_ID);
					bIsReadable  = acl.IsReadable();
					// 02/16/2011   We should allow a Read-Only field to be searchable, so always allow writing if the name contains Search. 
					bIsWriteable = acl.IsWriteable() || sEDIT_NAME.Contains(".Search");
				}

				// 11/25/2006   If Team Management has been disabled, then convert the field to a blank. 
				// Keep the field, but treat it as blank so that field indexes will still be valid. 
				// 12/03/2006   Allow the team field to be visible during layout. 
				if ( !bLayoutMode && (sDATA_FIELD == "TEAM_ID" || sDATA_FIELD == "TEAM_SET_NAME") )
				{
					if ( !bEnableTeamManagement )
					{
						sFIELD_TYPE = "Blank";
						bUI_REQUIRED = false;
					}
					else
					{
						// 08/28/2012   DATA_FORMAT for TEAM_ID is 1 when we want to force ModulePopup. 
						if ( bEnableDynamicTeams && sDATA_FORMAT != "1" )
						{
							// 08/31/2009   Don't convert to TeamSelect inside a Search view or Popup view. 
							if ( sEDIT_NAME.IndexOf(".Search") < 0 && sEDIT_NAME.IndexOf(".Popup") < 0 )
							{
								sDATA_LABEL     = ".LBL_TEAM_SET_NAME";
								sDATA_FIELD     = "TEAM_SET_NAME";
								sFIELD_TYPE     = "TeamSelect";
								sONCLICK_SCRIPT = String.Empty;
							}
						}
						else
						{
							// 04/18/2010   If the user manually adds a TeamSelect, we need to convert to a ModulePopup. 
							if ( sFIELD_TYPE == "TeamSelect" )
							{
								sDATA_LABEL     = "Teams.LBL_TEAM";
								sDATA_FIELD     = "TEAM_ID";
								sDISPLAY_FIELD  = "TEAM_NAME";
								sFIELD_TYPE     = "ModulePopup";
								sMODULE_TYPE    = "Teams";
								sONCLICK_SCRIPT = String.Empty;
							}
						}
						// 11/25/2006   Override the required flag with the system value. 
						// 01/01/2008   If Team Management is not required, then let the admin decide. 
						if ( bRequireTeamManagement )
							bUI_REQUIRED = true;
					}
				}
				// 12/13/2013   Allow each product to have a default tax rate. 
				if ( !bLayoutMode && sDATA_FIELD == "TAX_CLASS" )
				{
					if ( bEnableTaxLineItems )
					{
						// 08/28/2009   If dynamic teams are enabled, then always use the set name. 
						sDATA_LABEL = "ProductTemplates.LBL_TAXRATE_ID";
						sDATA_FIELD = "TAXRATE_ID";
						sCACHE_NAME = "TaxRates";
					}
				}
				// 04/04/2010   Hide the Exchange Folder field if disabled for this module or user. 
				if ( !bLayoutMode && sDATA_FIELD == "EXCHANGE_FOLDER" )
				{
					if ( !Crm.Modules.ExchangeFolders(sMODULE_NAME) || !Security.HasExchangeAlias() )
					{
						sFIELD_TYPE = "Blank";
					}
				}
				if ( !bLayoutMode && sDATA_FIELD == "ASSIGNED_USER_ID" )
				{
					// 01/01/2008   We need a quick way to require user assignments across the system. 
					if ( bRequireUserAssignment )
						bUI_REQUIRED = true;
				}
				if ( bIsMobile && String.Compare(sFIELD_TYPE, "AddressButtons", true) == 0 )
				{
					// 11/17/2007   Skip the address buttons on a mobile device. 
					continue;
				}
				// 01/18/2010   Clear the Required flag if the field is not writeable. 
				// Clearing at this stage will apply it to all edit types. 
				if ( bUI_REQUIRED && !bIsWriteable )
					bUI_REQUIRED = false;
				// 09/02/2012   A separator will create a new table. We need to match the outer and inner layout. 
				if ( String.Compare(sFIELD_TYPE, "Separator", true) == 0 )
				{
					if ( tbl.Parent.Parent.Parent is System.Web.UI.WebControls.Table )
					{
						System.Web.UI.WebControls.Table tblOuter = new System.Web.UI.WebControls.Table();
						tblOuter.SkinID = "tabForm";
						tblOuter.Style.Add(HtmlTextWriterStyle.MarginTop, "5px");
						// 09/27/2012   Separator can have an ID and can have a style so that it can be hidden. 
						if ( !Sql.IsEmptyString(sDATA_FIELD) )
							tblOuter.ID = sDATA_FIELD;
						if ( !Sql.IsEmptyString(sDATA_FORMAT) && !bLayoutMode )
							tblOuter.Style.Add(HtmlTextWriterStyle.Display, sDATA_FORMAT);
						int nParentIndex = tbl.Parent.Parent.Parent.Parent.Controls.IndexOf(tbl.Parent.Parent.Parent);
						tbl.Parent.Parent.Parent.Parent.Controls.AddAt(nParentIndex + 1, tblOuter);
						System.Web.UI.WebControls.TableRow trOuter = new System.Web.UI.WebControls.TableRow();
						tblOuter.Rows.Add(trOuter);
						System.Web.UI.WebControls.TableCell tdOuter = new System.Web.UI.WebControls.TableCell();
						trOuter.Cells.Add(tdOuter);
						System.Web.UI.HtmlControls.HtmlTable tblInner = new System.Web.UI.HtmlControls.HtmlTable();
						tblInner.Attributes.Add("class", "tabEditView");
						tdOuter.Controls.Add(tblInner);
						tbl = tblInner;
					
						nRowIndex = -1;
						nColIndex = 0;
						tdLabel = null;
						tdField = null;
						if ( bLayoutMode )
							tbl.Border = 1;
						else
							continue;
					}
				}
				// 11/17/2007   On a mobile device, each new field is on a new row. 
				// 12/02/2005  COLSPAN == -1 means that a new column should not be created. 
				if ( (nCOLSPAN >= 0 && nColIndex == 0) || tr == null || bIsMobile )
				{
					// 11/25/2005   Don't pre-create a row as we don't want a blank
					// row at the bottom.  Add rows just before they are needed. 
					nRowIndex++;
					tr = new HtmlTableRow();
					tbl.Rows.Insert(nRowIndex, tr);
				}
				if ( bLayoutMode )
				{
					HtmlTableCell tdAction = new HtmlTableCell();
					tr.Cells.Add(tdAction);
					tdAction.Attributes.Add("class", "tabDetailViewDL");
					tdAction.NoWrap = true;

					Literal litIndex = new Literal();
					tdAction.Controls.Add(litIndex);
					litIndex.Text = " " + nFIELD_INDEX.ToString() + " ";

					// 05/26/2007   Fix the terms. The are in the Dropdown module. 
					// 08/24/2009   Since this is the only area where we use the ID of the dynamic view record, only get it here. 
					Guid gID = Sql.ToGuid(row["ID"]);
					// 05/18/2013   Add drag handle. 
					if ( bSupportsDraggable )
					{
						Image imgDragIcon = new Image();
						imgDragIcon.SkinID = "draghandle_table";
						imgDragIcon.Attributes.Add("draggable"  , "true");
						imgDragIcon.Attributes.Add("ondragstart", "event.dataTransfer.setData('Text', '" + nFIELD_INDEX.ToString() + "');");
						tdAction.Controls.Add(imgDragIcon);
		
						tdAction.Attributes.Add("ondragover", "LayoutDragOver(event, '" + nFIELD_INDEX.ToString() + "')");
						tdAction.Attributes.Add("ondrop"    , "LayoutDropIndex(event, '" + nFIELD_INDEX.ToString() + "')");
					}
					else
					{
						ImageButton btnMoveUp   = CreateLayoutImageButtonSkin(gID, "Layout.MoveUp"  , nFIELD_INDEX, L10n.Term("Dropdown.LNK_UP"    ), "uparrow_inline"  , Page_Command);
						ImageButton btnMoveDown = CreateLayoutImageButtonSkin(gID, "Layout.MoveDown", nFIELD_INDEX, L10n.Term("Dropdown.LNK_DOWN"  ), "downarrow_inline", Page_Command);
						tdAction.Controls.Add(btnMoveUp  );
						tdAction.Controls.Add(btnMoveDown);
					}
					ImageButton btnInsert   = CreateLayoutImageButtonSkin(gID, "Layout.Insert"  , nFIELD_INDEX, L10n.Term("Dropdown.LNK_INS"   ), "plus_inline"     , Page_Command);
					ImageButton btnEdit     = CreateLayoutImageButtonSkin(gID, "Layout.Edit"    , nFIELD_INDEX, L10n.Term("Dropdown.LNK_EDIT"  ), "edit_inline"     , Page_Command);
					ImageButton btnDelete   = CreateLayoutImageButtonSkin(gID, "Layout.Delete"  , nFIELD_INDEX, L10n.Term("Dropdown.LNK_DELETE"), "delete_inline"   , Page_Command);
					tdAction.Controls.Add(btnInsert  );
					tdAction.Controls.Add(btnEdit    );
					tdAction.Controls.Add(btnDelete  );
				}
				// 12/03/2006   Move literal label up so that it can be accessed when processing a blank. 
				Literal litLabel = new Literal();
				if ( !Sql.IsEmptyString(sDATA_FIELD) && !hashLABEL_IDs.Contains(sDATA_FIELD) )
				{
					litLabel.ID = sDATA_FIELD + "_LABEL";
					hashLABEL_IDs.Add(sDATA_FIELD, null);
				}
				// 06/20/2009   The label and the field will be on separate rows for a NewRecord form. 
				HtmlTableRow trLabel = tr;
				HtmlTableRow trField = tr;
				if ( nCOLSPAN >= 0 || tdLabel == null || tdField == null )
				{
					tdLabel = new HtmlTableCell();
					tdField = new HtmlTableCell();
					trLabel.Cells.Add(tdLabel);
					if ( sLABEL_WIDTH == "100%" && sFIELD_WIDTH == "0%" && nDATA_COLUMNS == 1 )
					{
						nRowIndex++;
						trField = new HtmlTableRow();
						tbl.Rows.Insert(nRowIndex, trField);
					}
					else
					{
						// 06/20/2009   Don't specify the normal styles for a NewRecord form. 
						// This is so that the label will be left aligned. 
						tdLabel.Attributes.Add("class", "dataLabel");
						tdLabel.VAlign = "top";
						tdLabel.Width  = sLABEL_WIDTH;
						tdField.Attributes.Add("class", "dataField");
						tdField.VAlign = "top";
					}
					trField.Cells.Add(tdField);
					if ( nCOLSPAN > 0 )
					{
						tdField.ColSpan = nCOLSPAN;
						if ( bLayoutMode )
							tdField.ColSpan++;
					}
					// 11/28/2005   Don't use the field width if COLSPAN is specified as we want it to take the rest of the table.  The label width will be sufficient. 
					if ( nCOLSPAN == 0 && sFIELD_WIDTH != "0%" )
						tdField.Width  = sFIELD_WIDTH;

					tdLabel.Controls.Add(litLabel);
					// 01/18/2010   Apply ACL Field Security. 
					litLabel.Visible = bLayoutMode || bIsReadable;
					//litLabel.Text = nFIELD_INDEX.ToString() + " (" + nRowIndex.ToString() + "," + nColIndex.ToString() + ")";
					try
					{
						// 12/03/2006   Move code to blank able in layout mode to blank section below. 
						if ( bLayoutMode )
							litLabel.Text = sDATA_LABEL;
						else if ( sDATA_LABEL.IndexOf(".") >= 0 )
							litLabel.Text = L10n.Term(sDATA_LABEL);
						else if ( !Sql.IsEmptyString(sDATA_LABEL) && rdr != null )
						{
							// 01/27/2008   If the data label is not in the schema table, then it must be free-form text. 
							// It is not used often, but we allow the label to come from the result set.  For example,
							// when the parent is stored in the record, we need to pull the module name from the record. 
							litLabel.Text = sDATA_LABEL;
							// 11/22/2010   Convert data reader to data table for Rules Wizard. 
							if ( rdr != null )
							{
								//vwSchema.RowFilter = "ColumnName = '" + Sql.EscapeSQL(sDATA_LABEL) + "'";
								//if ( vwSchema.Count > 0 )
								if ( rdr.Table.Columns.Contains(sDATA_LABEL) )
									litLabel.Text = Sql.ToString(rdr[sDATA_LABEL]) + L10n.Term("Calls.LBL_COLON");
							}
						}
						// 07/15/2006   Always put something for the label so that table borders will look right. 
						// 07/20/2007 Vandalo.  Skip the requirement to create a terminology entry and just so the label. 
						else
							litLabel.Text = sDATA_LABEL;  // "&nbsp;";

						// 06/12/2009   Add Tool Tip hover. 
						// 11/23/2009   Only add tool tip if AJAX is available and this is not a mobile device. 
						// 01/18/2010   Only add tool tip if the label is visible. 
						if ( !bIsMobile && mgrAjax != null && !Sql.IsEmptyString(sTOOL_TIP) && !Sql.IsEmptyString(sDATA_FIELD) && litLabel.Visible )
						{
							Image imgToolTip = new Image();
							imgToolTip.SkinID = "tooltip_inline";
							imgToolTip.ID     = sDATA_FIELD + "_TOOLTIP_IMAGE";
							tdLabel.Controls.Add(imgToolTip);
							
							Panel pnlToolTip = new Panel();
							pnlToolTip.ID       = sDATA_FIELD + "_TOOLTIP_PANEL";
							pnlToolTip.CssClass = "tooltip";
							tdLabel.Controls.Add(pnlToolTip);

							Literal litToolTip = new Literal();
							litToolTip.Text = sDATA_FIELD;
							pnlToolTip.Controls.Add(litToolTip);
							if ( bLayoutMode )
								litToolTip.Text = sTOOL_TIP;
							else if ( sTOOL_TIP.IndexOf(".") >= 0 )
								litToolTip.Text = L10n.Term(sTOOL_TIP);
							else
								litToolTip.Text = sTOOL_TIP;
							
							AjaxControlToolkit.HoverMenuExtender hovToolTip = new AjaxControlToolkit.HoverMenuExtender();
							hovToolTip.TargetControlID = imgToolTip.ID;
							hovToolTip.PopupControlID  = pnlToolTip.ID;
							hovToolTip.PopupPosition   = AjaxControlToolkit.HoverMenuPopupPosition.Right;
							hovToolTip.PopDelay        = 50;
							hovToolTip.OffsetX         = 0;
							hovToolTip.OffsetY         = 0;
							tdLabel.Controls.Add(hovToolTip);
						}
					}
					catch(Exception ex)
					{
						SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						litLabel.Text = ex.Message;
					}
					if ( !bLayoutMode && bUI_REQUIRED )
					{
						Label lblRequired = new Label();
						tdLabel.Controls.Add(lblRequired);
						lblRequired.CssClass = "required";
						lblRequired.Text = L10n.Term(".LBL_REQUIRED_SYMBOL");
					}
				}
				
				if ( String.Compare(sFIELD_TYPE, "Blank", true) == 0 )
				{
					// 06/20/2009   There is no need for blank fields in a NewRecord form. 
					// By hiding them we are able to properly disable Team selection when Team Mangement is disabled. 
					if ( sLABEL_WIDTH == "100%" && sFIELD_WIDTH == "0%" && nDATA_COLUMNS == 1 )
					{
						trLabel.Visible = false;
						trField.Visible = false;
					}
					else
					{
						Literal litField = new Literal();
						tdField.Controls.Add(litField);
						if ( bLayoutMode )
						{
							litLabel.Text = "*** BLANK ***";
							litField.Text = "*** BLANK ***";
						}
						else
						{
							// 12/03/2006   Make sure to clear the label.  This is necessary to convert a TEAM to blank when disabled. 
							litLabel.Text = "&nbsp;";
							litField.Text = "&nbsp;";
						}
					}
				}
				// 09/03/2012   A separator does nothing in Layout mode. 
				else if ( String.Compare(sFIELD_TYPE, "Separator", true) == 0 )
				{
					if ( bLayoutMode )
					{
						litLabel.Text = "*** SEPARATOR ***";
						nColIndex = nDATA_COLUMNS;
						tdField.ColSpan = 2 * nDATA_COLUMNS - 1;
						// 09/03/2012   When in layout mode, we need to add a column for arrangement. 
						tdField.ColSpan++;
					}
				}
				// 09/02/2012   A header is similar to a label, but without the data field. 
				else if ( String.Compare(sFIELD_TYPE, "Header", true) == 0 )
				{
					if ( !bLayoutMode )
						litLabel.Text = "<h4>" + litLabel.Text + "</h4>";
					tdLabel.ColSpan = 2;
					tdField.Visible = false;
				}
				else if ( String.Compare(sFIELD_TYPE, "Label", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 05/23/2014   Use a label instead of a literal so that the field can be accessed using HTML DOM. 
						Label litField = new Label();
						tdField.Controls.Add(litField);
						// 07/25/2006   Align label values to the middle so the line-up with the label. 
						tdField.VAlign = "middle";
						// 07/24/2006   Set the ID so that the literal control can be accessed. 
						litField.ID = sDATA_FIELD;
						// 01/18/2010   Apply ACL Field Security. 
						// 10/07/2010   We need to apply ACL on each part of the label. 
						//litField.Visible = bLayoutMode || bIsReadable;
						try
						{
							if ( bLayoutMode )
								litField.Text = sDATA_FIELD;
/*
							else if ( sDATA_FIELD.IndexOf(".") >= 0 )
								litField.Text = L10n.Term(sDATA_FIELD);
							else if ( rdr != null )
								litField.Text = Sql.ToString(rdr[sDATA_FIELD]);
*/
							// 10/07/2010   Allow a label to contain multiple data entries. 
							else
							{
								string[] arrDATA_FIELD = sDATA_FIELD.Split(' ');
								object[] objDATA_FIELD = new object[arrDATA_FIELD.Length];
								for ( int i=0 ; i < arrDATA_FIELD.Length; i++ )
								{
									if ( arrDATA_FIELD[i].IndexOf(".") >= 0 )
									{
										objDATA_FIELD[i] = L10n.Term(arrDATA_FIELD[i]);
									}
									else if ( !Sql.IsEmptyString(arrDATA_FIELD[i]) )
									{
										bIsReadable = true;
										if ( SplendidInit.bEnableACLFieldSecurity )
										{
											Security.ACL_FIELD_ACCESS acl = Security.GetUserFieldSecurity(sMODULE_NAME, sDATA_FIELD, gASSIGNED_USER_ID);
											bIsReadable  = acl.IsReadable();
										}
										if ( bIsReadable && rdr != null && rdr[arrDATA_FIELD[i]] != DBNull.Value)
										{
											// 12/05/2005   If the data is a DateTime field, then make sure to perform the timezone conversion. 
											if ( rdr[arrDATA_FIELD[i]].GetType() == Type.GetType("System.DateTime") )
												objDATA_FIELD[i] = T10n.FromServerTime(rdr[arrDATA_FIELD[i]]);
											// 02/16/2010   Add MODULE_TYPE so that we can lookup custom field IDs. 
											// 02/16/2010   Move ToGuid to the function so that it can be captured if invalid. 
											else if ( !Sql.IsEmptyString(sMODULE_TYPE) )
												objDATA_FIELD[i] = Crm.Modules.ItemName(Application, sMODULE_TYPE, rdr[arrDATA_FIELD[i]]);
											else
												objDATA_FIELD[i] = rdr[arrDATA_FIELD[i]];
										}
										else
											objDATA_FIELD[i] = String.Empty;
									}
								}
								// 08/28/2012   We do not need the record to display a label. 
								//if ( rdr != null )
								{
									// 10/07/2010   There is a special case where we are show a date and a user name. 
									if ( arrDATA_FIELD.Length == 3 && objDATA_FIELD.Length == 3 && arrDATA_FIELD[1] == ".LBL_BY" && Sql.IsEmptyString(objDATA_FIELD[0]) && Sql.IsEmptyString(objDATA_FIELD[2]) )
										litField.Text = String.Empty;
									else
									// 01/09/2006   Allow DATA_FORMAT to be optional.   If missing, write data directly. 
									if ( sDATA_FORMAT == String.Empty )
									{
										for ( int i=0; i < arrDATA_FIELD.Length; i++ )
											arrDATA_FIELD[i] = Sql.ToString(objDATA_FIELD[i]);
										litField.Text = String.Join(" ", arrDATA_FIELD);
									}
									else if ( sDATA_FORMAT == "{0:c}" && C10n != null )
									{
										// 03/30/2007   Convert DetailView currencies on the fly. 
										// 05/05/2007   In an earlier step, we convert NULLs to empty strings. 
										// Attempts to convert to decimal will generate an error: Input string was not in a correct format.
										if ( !(objDATA_FIELD[0] is string) )
										{
											Decimal d = C10n.ToCurrency(Convert.ToDecimal(objDATA_FIELD[0]));
											litField.Text = d.ToString("c");
										}
									}
									else
										litField.Text = String.Format(sDATA_FORMAT, objDATA_FIELD);
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							litField.Text = ex.Message;
						}
					}
				}
				// 09/13/2010   Add relationship fields. 
				else if ( String.Compare(sFIELD_TYPE, "RelatedSelect", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) && !Sql.IsEmptyString(sRELATED_SOURCE_MODULE_NAME) && bVALID_RELATED )
					{
						RelatedSelect ctlRelatedSelect = tbl.Page.LoadControl("~/_controls/RelatedSelect.ascx") as RelatedSelect;
						tdField.Controls.Add(ctlRelatedSelect);
						// 09/18/2010   Using a "." in the ID caused major AJAX failures that were hard to debug. 
						//ctlRelatedSelect.ID                           = sRELATED_VIEW_NAME + "_" + sRELATED_ID_FIELD;
						// 10/14/2011   We must use sDATA_FIELD as the ID until we can change UpdateCustomFields() to use the related ID. 
						ctlRelatedSelect.ID                           = sDATA_FIELD;
						ctlRelatedSelect.RELATED_SOURCE_MODULE_NAME   = sRELATED_SOURCE_MODULE_NAME  ;
						ctlRelatedSelect.RELATED_SOURCE_VIEW_NAME     = sRELATED_SOURCE_VIEW_NAME    ;
						ctlRelatedSelect.RELATED_SOURCE_ID_FIELD      = sRELATED_SOURCE_ID_FIELD     ;
						ctlRelatedSelect.RELATED_SOURCE_NAME_FIELD    = sRELATED_SOURCE_NAME_FIELD   ;
						ctlRelatedSelect.RELATED_VIEW_NAME            = sRELATED_VIEW_NAME           ;
						ctlRelatedSelect.RELATED_ID_FIELD             = sRELATED_ID_FIELD            ;
						ctlRelatedSelect.RELATED_NAME_FIELD           = sRELATED_NAME_FIELD          ;
						ctlRelatedSelect.RELATED_JOIN_FIELD           = sRELATED_JOIN_FIELD          ;

						ctlRelatedSelect.NotPostBack = bNotPostBack;
						ctlRelatedSelect.Visible  = bLayoutMode || bIsReadable;
						ctlRelatedSelect.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							Guid gPARENT_ID = Guid.Empty;
							if ( rdr != null )
							{
								try
								{
									gPARENT_ID = Sql.ToGuid(rdr[sDATA_FIELD]);
								}
								catch
								{
								}
							}
							ctlRelatedSelect.LoadLineItems(gPARENT_ID);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "RelatedListBox", true) == 0 || String.Compare(sFIELD_TYPE, "RelatedCheckBoxList", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) && bVALID_RELATED )
					{
						ListControl lstField = new RadioButtonList();
						if ( String.Compare(sFIELD_TYPE, "RelatedListBox", true) == 0 )
						{
							lstField = new ListBox();
							(lstField as ListBox).SelectionMode = ListSelectionMode.Multiple;
							(lstField as ListBox).Rows          = (nFORMAT_ROWS == 0) ? 6 : nFORMAT_ROWS;
							tdField.Controls.Add(lstField);
						}
						else if ( String.Compare(sFIELD_TYPE, "RelatedCheckBoxList", true) == 0 )
						{
							lstField = new CheckBoxList();
							lstField.CssClass = "checkbox";
							// 09/16/2010   Put inside a div so that we can use auto-scroll. 
							if ( nFORMAT_ROWS > 0 )
							{
								HtmlGenericControl div = new HtmlGenericControl("div");
								div.Controls.Add(lstField);
								tdField.Controls.Add(div);
								div.Attributes.Add("style", "overflow-y: auto;height: " + nFORMAT_ROWS.ToString() + "px");
							}
							else
							{
								tdField.Controls.Add(lstField);
							}
						}
						else
						{
							lstField.CssClass = "radio";
							// 09/16/2010   Put inside a div so that we can use auto-scroll. 
							if ( nFORMAT_ROWS > 0 )
							{
								HtmlGenericControl div = new HtmlGenericControl("div");
								div.Controls.Add(lstField);
								tdField.Controls.Add(div);
								div.Attributes.Add("style", "overflow-y: auto;height: " + nFORMAT_ROWS.ToString() + "px");
							}
							else
							{
								tdField.Controls.Add(lstField);
							}
						}
						// 09/13/2010   We should not use the sDATA_FIELD as it might be identical for multiple RelatedListBox.  For example, it could be the ID of the record. 
						// 09/18/2010   Using a "." in the ID caused major AJAX failures that were hard to debug. 
						//lstField.ID            = sRELATED_VIEW_NAME + "_" + sRELATED_ID_FIELD;// sDATA_FIELD;
						// 10/14/2011   We must use sDATA_FIELD as the ID until we can change UpdateCustomFields() to use the related ID. 
						lstField.ID            = sDATA_FIELD;
						lstField.TabIndex      = nFORMAT_TAB_INDEX;
						lstField.Visible       = bLayoutMode || bIsReadable;
						lstField.Enabled       = bLayoutMode || bIsWriteable;
						try
						{
							// 09/13/2010   As extra precaution, make sure that the table name is valid. 
							Regex r = new Regex(@"[^A-Za-z0-9_]");
							sRELATED_SOURCE_VIEW_NAME     = r.Replace(sRELATED_SOURCE_VIEW_NAME    , "");
							sRELATED_SOURCE_ID_FIELD      = r.Replace(sRELATED_SOURCE_ID_FIELD     , "");
							sRELATED_SOURCE_NAME_FIELD    = r.Replace(sRELATED_SOURCE_NAME_FIELD   , "");
							sRELATED_VIEW_NAME            = r.Replace(sRELATED_VIEW_NAME           , "");
							sRELATED_ID_FIELD             = r.Replace(sRELATED_ID_FIELD            , "");
							sRELATED_NAME_FIELD           = r.Replace(sRELATED_NAME_FIELD          , "");
							sRELATED_JOIN_FIELD           = r.Replace(sRELATED_JOIN_FIELD          , "");

							// 09/13/2010   Add relationship fields, Don't populate list if this is a post back. 
							if ( (bLayoutMode || !bIsPostBack) )
							{
								lstField.DataValueField = sRELATED_SOURCE_ID_FIELD  ;
								lstField.DataTextField  = sRELATED_SOURCE_NAME_FIELD;
								DbProviderFactory dbf = DbProviderFactories.GetFactory();
								using ( IDbConnection con = dbf.CreateConnection() )
								{
									con.Open();
									string sSQL;
									sSQL = "select " + sRELATED_SOURCE_ID_FIELD      + ControlChars.CrLf
									     + "     , " + sRELATED_SOURCE_NAME_FIELD    + ControlChars.CrLf
									     + "  from " + sRELATED_SOURCE_VIEW_NAME     + ControlChars.CrLf
									     + " order by " + sRELATED_SOURCE_NAME_FIELD + ControlChars.CrLf;
									using ( IDbCommand cmd = con.CreateCommand() )
									{
										cmd.CommandText = sSQL;
										// 09/13/2010   When in layout mode, only fetch 10 records. 
										if ( bLayoutMode )
											Sql.LimitResults(cmd, 10);
										using ( DbDataAdapter da = dbf.CreateDataAdapter() )
										{
											((IDbDataAdapter)da).SelectCommand = cmd;
											DataTable dt = new DataTable();
											da.Fill(dt);
											lstField.DataSource = dt;
											lstField.DataBind();
										}
									}
								}
								if ( !Sql.IsEmptyString(sONCLICK_SCRIPT) )
									lstField.Attributes.Add("onchange" , sONCLICK_SCRIPT);
								// 10/02/2010   None does not seem appropriate for related data. 
								/*
								if ( !bUI_REQUIRED )
								{
									lstField.Items.Insert(0, new ListItem(L10n.Term(".LBL_NONE"), ""));
									lstField.DataBound += new EventHandler(ListControl_DataBound_AllowNull);
								}
								*/
							}
							if ( rdr != null )
							{
								try
								{
									// 10/14/2011   When settings values, there does not seem to be a good reason to do another database lookup. 
									// The lstField binding means that the values are there. 
									if ( rdr[sDATA_FIELD].GetType() == typeof(Guid) )
									{
										string sVALUE = Sql.ToGuid(rdr[sDATA_FIELD]).ToString();
										foreach ( ListItem item in lstField.Items )
										{
											if ( item.Value == sVALUE )
												item.Selected = true;
										}
									}
									else
									{
										List<string> arrVALUE = new List<string>();
										// 10/14/2011   If this is a multi-selection, then we need to get the list if values. 
										string sVALUE = Sql.ToString(rdr[sDATA_FIELD]);
										if ( sVALUE.StartsWith("<?xml") )
										{
											XmlDocument xml = new XmlDocument();
											xml.LoadXml(sVALUE);
											XmlNodeList nlValues = xml.DocumentElement.SelectNodes("Value");
											foreach ( XmlNode xValue in nlValues )
											{
												foreach ( ListItem item in lstField.Items )
												{
													if ( item.Value == xValue.InnerText )
														item.Selected = true;
												}
											}
										}
										else
										{
											foreach ( ListItem item in lstField.Items )
											{
												if ( item.Value == sVALUE )
													item.Selected = true;
											}
										}
									}
								}
								catch(Exception ex)
								{
									SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								}
							}
							// 12/04/2005   Assigned To field will always default to the current user. 
							else if ( rdr == null && !bIsPostBack && sCACHE_NAME == "AssignedUser")
							{
								try
								{
									// 12/02/2007   We don't default the user when using multi-selection.  
									// This is because this mode is typically used for searching. 
									if ( nFORMAT_ROWS == 0 )
										// 08/19/2010   Check the list before assigning the value. 
										Utils.SetValue(lstField, Security.USER_ID.ToString());
								}
								catch(Exception ex)
								{
									SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "ListBox", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/02/2007   If format rows > 0 then this is a list box and not a drop down list. 
						ListControl lstField = null;
						if ( nFORMAT_ROWS > 0 )
						{
							ListBox lb = new ListBox();
							lb.SelectionMode = ListSelectionMode.Multiple;
							lb.Rows          = nFORMAT_ROWS;
							lstField = lb;
						}
						else
						{
							// 04/25/2008   Use KeySortDropDownList instead of ListSearchExtender. 
							lstField = new KeySortDropDownList();
							// 07/26/2010   Lets try the latest version of the ListSearchExtender. 
							// 07/28/2010   We are getting an undefined exception on the Accounts List Advanced page. 
							// Lets drop back to using KeySort. 
							//lstField = new DropDownList();
						}
						tdField.Controls.Add(lstField);
						lstField.ID       = sDATA_FIELD;
						lstField.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						lstField.Visible  = bLayoutMode || bIsReadable;
						lstField.Enabled  = bLayoutMode || bIsWriteable;

						try
						{
							// 10/09/2010   Add PARENT_FIELD so that we can establish dependent listboxes. 
							if ( !Sql.IsEmptyString(sPARENT_FIELD) )
							{
								ListControl lstPARENT_FIELD = tbl.FindControl(sPARENT_FIELD) as ListControl;
								if ( lstPARENT_FIELD != null )
								{
									lstPARENT_FIELD.AutoPostBack = true;
									// 11/02/2010   We need a way to insert NONE into the a ListBox while still allowing multiple rows. 
									// The trick will be to use a negative number.  Use an absolute value here to reduce the areas to fix. 
									EditViewEventManager mgr = new EditViewEventManager(lstPARENT_FIELD, lstField, bUI_REQUIRED, Sql.ToInteger(row["FORMAT_ROWS"]), L10n);
									lstPARENT_FIELD.SelectedIndexChanged += new EventHandler(mgr.SelectedIndexChanged);
									if ( !bIsPostBack && lstPARENT_FIELD.SelectedIndex >= 0 )
									{
										sCACHE_NAME = lstPARENT_FIELD.SelectedValue;
									}
								}
							}
							// 12/04/2005   Don't populate list if this is a post back. 
							if ( !Sql.IsEmptyString(sCACHE_NAME) && (bLayoutMode || !bIsPostBack) )
							{
								// 12/24/2007   Use an array to define the custom caches so that list is in the Cache module. 
								// This should reduce the number of times that we have to edit the SplendidDynamic module. 
								// 02/16/2012   Move custom cache logic to a method. 
								SplendidCache.SetListSource(sCACHE_NAME, lstField);
								lstField.DataBind();
								// 08/08/2006   Allow onchange code to be stored in the database.  
								// ListBoxes do not have a useful onclick event, so there should be no problem overloading this field. 
								if ( !Sql.IsEmptyString(sONCLICK_SCRIPT) )
									lstField.Attributes.Add("onchange" , sONCLICK_SCRIPT);
								// 02/21/2006   Move the NONE item inside the !IsPostBack code. 
								// 12/02/2007   We don't need a NONE record when using multi-selection. 
								// 12/03/2007   We do want the NONE record when using multi-selection. 
								// This will allow searching of fields that are null instead of using the unassigned only checkbox. 
								// 10/02/2010   It does not seem logical to allow a NONE option on a multi-selection listbox. 
								// 11/02/2010   We need a way to insert NONE into the a ListBox while still allowing multiple rows. 
								// The trick will be to use a negative number.  Use an absolute value here to reduce the areas to fix. 
								if ( !bUI_REQUIRED && Sql.ToInteger(row["FORMAT_ROWS"]) <= 0 )
								{
                                    lstField.Items.Insert(0, new ListItem("--È«²¿--",""));

                                    /*
									lstField.Items.Insert(0, new ListItem(L10n.Term(".LBL_NONE"), ""));
									// 12/02/2007   AppendEditViewFields should be called inside Page_Load when not a postback, 
									// and in InitializeComponent when it is a postback. If done wrong, 
									// the page will bind after the list is populated, causing the list to populate again. 
									// This event will cause the NONE entry to be cleared.  Add a handler to catch this problem, 
									// but the real solution is to call AppendEditViewFields at the appropriate times based on the postback event. 
									lstField.DataBound += new EventHandler(ListControl_DataBound_AllowNull);
                                     */
								}
								// 01/20/2010   Set the default value for Currencies. 
								if ( !bLayoutMode && rdr == null && !bIsPostBack && sCACHE_NAME == "Currencies" )
								{
									try
									{
										Guid gCURRENCY_ID = Sql.ToGuid(HttpContext.Current.Session["USER_SETTINGS/CURRENCY"]);
										// 08/19/2010   Check the list before assigning the value. 
										Utils.SetValue(lstField, gCURRENCY_ID.ToString());
									}
									catch
									{
									}
								}
							}
							if ( rdr != null )
							{
								try
								{
									// 02/21/2006   All the DropDownLists in the Calls and Meetings edit views were not getting set.  
									// The problem was a Page.DataBind in the SchedulingGrid and in the InviteesView. Both binds needed to be removed. 
									// 12/30/2007   A customer needed the ability to save and restore the multiple selection. 
									// 12/30/2007   Require the XML declaration in the data before trying to treat as XML. 
									string sVALUE = Sql.ToString(rdr[sDATA_FIELD]);
									if ( nFORMAT_ROWS > 0 && sVALUE.StartsWith("<?xml") )
									{
										XmlDocument xml = new XmlDocument();
										xml.LoadXml(sVALUE);
										XmlNodeList nlValues = xml.DocumentElement.SelectNodes("Value");
										foreach ( XmlNode xValue in nlValues )
										{
											foreach ( ListItem item in lstField.Items )
											{
												if ( item.Value == xValue.InnerText )
													item.Selected = true;
											}
										}
									}
									else
									{
										// 08/19/2010   Check the list before assigning the value. 
										Utils.SetValue(lstField, sVALUE);
									}
								}
								catch(Exception ex)
								{
									SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								}
							}
							// 12/04/2005   Assigned To field will always default to the current user. 
							else if ( rdr == null && !bIsPostBack && sCACHE_NAME == "AssignedUser")
							{
								try
								{
									// 12/02/2007   We don't default the user when using multi-selection.  
									// This is because this mode is typically used for searching. 
									if ( nFORMAT_ROWS == 0 )
										// 08/19/2010   Check the list before assigning the value. 
										Utils.SetValue(lstField, Security.USER_ID.ToString());
								}
								catch(Exception ex)
								{
									SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				// 06/16/2010   Add support for CheckBoxList. 
				else if ( String.Compare(sFIELD_TYPE, "CheckBoxList", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/02/2007   If format rows > 0 then this is a list box and not a drop down list. 
						ListControl lstField = new CheckBoxList();
						// 09/16/2010   Put inside a div so that we can use auto-scroll. 
						if ( nFORMAT_ROWS > 0 )
						{
							HtmlGenericControl div = new HtmlGenericControl("div");
							div.Controls.Add(lstField);
							tdField.Controls.Add(div);
							div.Attributes.Add("style", "overflow-y: auto;height: " + nFORMAT_ROWS.ToString() + "px");
						}
						else
						{
							tdField.Controls.Add(lstField);
						}
						lstField.ID       = sDATA_FIELD;
						lstField.TabIndex = nFORMAT_TAB_INDEX;
						lstField.CssClass = "checkbox";
						// 01/18/2010   Apply ACL Field Security. 
						lstField.Visible  = bLayoutMode || bIsReadable;
						lstField.Enabled  = bLayoutMode || bIsWriteable;
						// 03/22/2013   Allow horizontal CheckBoxList. 
						if ( sDATA_FORMAT == "1" )
						{
							(lstField as CheckBoxList).RepeatDirection = System.Web.UI.WebControls.RepeatDirection.Horizontal;
							(lstField as CheckBoxList).RepeatLayout    = System.Web.UI.WebControls.RepeatLayout.Flow;
						}
						try
						{
							if ( !Sql.IsEmptyString(sDATA_FIELD) )
							{
								// 12/04/2005   Don't populate list if this is a post back. 
								if ( !Sql.IsEmptyString(sCACHE_NAME) && (bLayoutMode || !bIsPostBack) )
								{
									// 12/24/2007   Use an array to define the custom caches so that list is in the Cache module. 
									// This should reduce the number of times that we have to edit the SplendidDynamic module. 
									// 02/16/2012   Move custom cache logic to a method. 
									SplendidCache.SetListSource(sCACHE_NAME, lstField);
									lstField.DataBind();
								}
								if ( rdr != null )
								{
									try
									{
										string sVALUE = Sql.ToString(rdr[sDATA_FIELD]);
										if ( sVALUE.StartsWith("<?xml") )
										{
											XmlDocument xml = new XmlDocument();
											xml.LoadXml(sVALUE);
											XmlNodeList nlValues = xml.DocumentElement.SelectNodes("Value");
											foreach ( XmlNode xValue in nlValues )
											{
												foreach ( ListItem item in lstField.Items )
												{
													if ( item.Value == xValue.InnerText )
														item.Selected = true;
												}
											}
										}
										// 03/22/2013   REPEAT_DOW is a special list that returns 0 = sunday, 1 = monday, etc. 
										else if ( sDATA_FIELD == "REPEAT_DOW" )
										{
											for ( int i = 0; i < lstField.Items.Count; i++ )
											{
												if ( sVALUE.Contains(i.ToString()) )
													lstField.Items[i].Selected = true;
											}
										}
										else
										{
											// 08/19/2010   Check the list before assigning the value. 
											Utils.SetValue(lstField, sVALUE);
										}
									}
									catch(Exception ex)
									{
										SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
									}
								}
								// 12/04/2005   Assigned To field will always default to the current user. 
								else if ( rdr == null && !bIsPostBack && sCACHE_NAME == "AssignedUser")
								{
									try
									{
										// 08/19/2010   Check the list before assigning the value. 
										Utils.SetValue(lstField, Security.USER_ID.ToString());
									}
									catch(Exception ex)
									{
										SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
									}
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				// 06/16/2010   Add support for Radio buttons. 
				else if ( String.Compare(sFIELD_TYPE, "Radio", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						ListControl lstField = new RadioButtonList();
						// 09/16/2010   Put inside a div so that we can use auto-scroll. 
						if ( nFORMAT_ROWS > 0 )
						{
							HtmlGenericControl div = new HtmlGenericControl("div");
							div.Controls.Add(lstField);
							tdField.Controls.Add(div);
							div.Attributes.Add("style", "overflow-y: auto;height: " + nFORMAT_ROWS.ToString() + "px");
						}
						else
						{
							tdField.Controls.Add(lstField);
						}
						lstField.ID       = sDATA_FIELD;
						lstField.TabIndex = nFORMAT_TAB_INDEX;
						lstField.CssClass = "radio";
						// 01/18/2010   Apply ACL Field Security. 
						lstField.Visible  = bLayoutMode || bIsReadable;
						lstField.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							if ( !Sql.IsEmptyString(sDATA_FIELD) )
							{
								// 12/04/2005   Don't populate list if this is a post back. 
								if ( !Sql.IsEmptyString(sCACHE_NAME) && (bLayoutMode || !bIsPostBack) )
								{
									// 12/24/2007   Use an array to define the custom caches so that list is in the Cache module. 
									// This should reduce the number of times that we have to edit the SplendidDynamic module. 
									// 02/16/2012   Move custom cache logic to a method. 
									SplendidCache.SetListSource(sCACHE_NAME, lstField);
									lstField.DataBind();
									// 08/08/2006   Allow onchange code to be stored in the database.  
									// ListBoxes do not have a useful onclick event, so there should be no problem overloading this field. 
									if ( !Sql.IsEmptyString(sONCLICK_SCRIPT) )
										lstField.Attributes.Add("onchange" , sONCLICK_SCRIPT);
									// 02/21/2006   Move the NONE item inside the !IsPostBack code. 
									// 12/02/2007   We don't need a NONE record when using multi-selection. 
									// 12/03/2007   We do want the NONE record when using multi-selection. 
									// This will allow searching of fields that are null instead of using the unassigned only checkbox. 
									if ( !bUI_REQUIRED )
									{
										lstField.Items.Insert(0, new ListItem(L10n.Term(".LBL_NONE"), ""));
										// 12/02/2007   AppendEditViewFields should be called inside Page_Load when not a postback, 
										// and in InitializeComponent when it is a postback. If done wrong, 
										// the page will bind after the list is populated, causing the list to populate again. 
										// This event will cause the NONE entry to be cleared.  Add a handler to catch this problem, 
										// but the real solution is to call AppendEditViewFields at the appropriate times based on the postback event. 
										lstField.DataBound += new EventHandler(ListControl_DataBound_AllowNull);
									}
									else
									{
										// 06/16/2010   If the UI is required for Radio buttons, then we need to set the first item. 
										if ( !bIsPostBack && rdr == null )
										{
											lstField.SelectedIndex = 0;
										}
									}
									// 01/20/2010   Set the default value for Currencies. 
									if ( !bLayoutMode && rdr == null && !bIsPostBack && sCACHE_NAME == "Currencies" )
									{
										try
										{
											Guid gCURRENCY_ID = Sql.ToGuid(HttpContext.Current.Session["USER_SETTINGS/CURRENCY"]);
											// 08/19/2010   Check the list before assigning the value. 
											Utils.SetValue(lstField, gCURRENCY_ID.ToString());
										}
										catch
										{
										}
									}
								}
								if ( rdr != null )
								{
									try
									{
										// 02/21/2006   All the DropDownLists in the Calls and Meetings edit views were not getting set.  
										// The problem was a Page.DataBind in the SchedulingGrid and in the InviteesView. Both binds needed to be removed. 
										// 12/30/2007   A customer needed the ability to save and restore the multiple selection. 
										// 12/30/2007   Require the XML declaration in the data before trying to treat as XML. 
										string sVALUE = Sql.ToString(rdr[sDATA_FIELD]);
										if ( nFORMAT_ROWS > 0 && sVALUE.StartsWith("<?xml") )
										{
											XmlDocument xml = new XmlDocument();
											xml.LoadXml(sVALUE);
											XmlNodeList nlValues = xml.DocumentElement.SelectNodes("Value");
											foreach ( XmlNode xValue in nlValues )
											{
												foreach ( ListItem item in lstField.Items )
												{
													if ( item.Value == xValue.InnerText )
														item.Selected = true;
												}
											}
										}
										else
										{
											// 08/19/2010   Check the list before assigning the value. 
											Utils.SetValue(lstField, sVALUE);
										}
									}
									catch(Exception ex)
									{
										SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
									}
								}
								// 12/04/2005   Assigned To field will always default to the current user. 
								else if ( rdr == null && !bIsPostBack && sCACHE_NAME == "AssignedUser")
								{
									try
									{
										// 12/02/2007   We don't default the user when using multi-selection.  
										// This is because this mode is typically used for searching. 
										if ( nFORMAT_ROWS == 0 )
											// 08/19/2010   Check the list before assigning the value. 
											Utils.SetValue(lstField, Security.USER_ID.ToString());
									}
									catch(Exception ex)
									{
										SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
									}
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "CheckBox", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						CheckBox chkField = new CheckBox();
						tdField.Controls.Add(chkField);
						chkField.ID = sDATA_FIELD;
						chkField.CssClass = "checkbox";
						chkField.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						chkField.Visible  = bLayoutMode || bIsReadable;
						chkField.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							if ( rdr != null )
								chkField.Checked = Sql.ToBoolean(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						// 07/11/2007   A checkbox can have a click event. 
						if ( !Sql.IsEmptyString(sONCLICK_SCRIPT) )
							chkField.Attributes.Add("onclick", sONCLICK_SCRIPT);
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
							chkField.Enabled  = false     ;
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "ChangeButton", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						//05/06/2010   Manually generate ClearModuleType so that it will be UpdatePanel safe. 
						DropDownList lstField = null;
						// 12/04/2005   If the label is PARENT_TYPE, then change the label to a DropDownList.
						if ( sDATA_LABEL == "PARENT_TYPE" )
						{
							tdLabel.Controls.Clear();
							// 04/25/2008   Use KeySortDropDownList instead of ListSearchExtender. 
							// 01/13/2010   KeySortDropDownList is causing OnChange will always fire when tabbed-away. 
							// For the Parent DropDownList, we don't need the KeySort as it is a short list. 
							//DropDownList lstField = new KeySortDropDownList();
							lstField = new DropDownList();
							tdLabel.Controls.Add(lstField);
							// 11/11/2010   Give the parent type a unique name. 
							// 02/04/2011   We gave the PARENT_TYPE a unique name, but we need to update all EditViews and NewRecords. 
							lstField.ID       = sDATA_FIELD + "_PARENT_TYPE";
							lstField.TabIndex = nFORMAT_TAB_INDEX;
							// 04/02/2013   Apply ACL Field Security to Parent Type field. 
							if ( SplendidInit.bEnableACLFieldSecurity )
							{
								Security.ACL_FIELD_ACCESS acl = Security.GetUserFieldSecurity(sMODULE_NAME, "PARENT_TYPE", gASSIGNED_USER_ID);
								lstField.Visible  = bLayoutMode || acl.IsReadable();
								lstField.Enabled  = bLayoutMode || acl.IsWriteable() || sEDIT_NAME.Contains(".Search");
							}
							
							
							// 04/25/2008   Add AJAX searching of list. 
							// 04/25/2008   ListSearchExtender needs work.  I don't like the delay when a list is selected
							// and there are problems when the browser window is scrolled.  KeySortDropDownList is a better solution. 
							// 07/23/2010   Lets try the latest version of the ListSearchExtender. 
							// 07/28/2010   We are getting an undefined exception on the Accounts List Advanced page. 
							/*
							AjaxControlToolkit.ListSearchExtender extField = new AjaxControlToolkit.ListSearchExtender();
							extField.ID              = lstField.ID + "_ListSearchExtender";
							extField.TargetControlID = lstField.ID;
							extField.PromptText      = L10n.Term(".LBL_TYPE_TO_SEARCH");
							extField.PromptCssClass  = "ListSearchExtenderPrompt";
							tdLabel.Controls.Add(extField);
							*/
							if ( bLayoutMode || !bIsPostBack )
							{
								// 07/29/2005   SugarCRM 3.0 does not allow the NONE option. 
								lstField.DataValueField = "NAME"        ;
								lstField.DataTextField  = "DISPLAY_NAME";
								lstField.DataSource     = SplendidCache.List("record_type_display");
								lstField.DataBind();
								if ( rdr != null )
								{
									try
									{
										// 08/19/2010   Check the list before assigning the value. 
										Utils.SetValue(lstField, Sql.ToString(rdr[sDATA_LABEL]));
									}
									catch(Exception ex)
									{
										SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
									}
								}
							}
						}
						TextBox txtNAME = new TextBox();
						tdField.Controls.Add(txtNAME);
						txtNAME.ID       = sDISPLAY_FIELD;
						txtNAME.ReadOnly = true;
						txtNAME.TabIndex = nFORMAT_TAB_INDEX;
						// 11/25/2006    Turn off viewstate so that we can fix the text on postback. 
						txtNAME.EnableViewState = false;
						// 01/18/2010   Apply ACL Field Security. 
						txtNAME.Visible  = bLayoutMode || bIsReadable;
						txtNAME.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							if ( bLayoutMode )
							{
								txtNAME.Text    = sDISPLAY_FIELD;
								txtNAME.Enabled = false         ;
							}
							// 11/25/2006   The Change text field is losing its value during a postback error. 
							else if ( bIsPostBack )
							{
								// 11/25/2006   In order for this posback fix to work, viewstate must be disabled for this field. 
								if ( tbl.Page.Request[txtNAME.UniqueID] != null )
									txtNAME.Text = Sql.ToString(tbl.Page.Request[txtNAME.UniqueID]);
							}
							else if ( !Sql.IsEmptyString(sDISPLAY_FIELD) && rdr != null )
								txtNAME.Text = Sql.ToString(rdr[sDISPLAY_FIELD]);
							// 11/25/2006   The team name should always default to the current user's private team. 
							// Make sure not to overwrite the value if this is a postback. 
							// 08/26/2009   Don't prepopulate team or user if in a search dialog. 
							else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "TEAM_ID" && rdr == null && !bIsPostBack )
								txtNAME.Text = Security.TEAM_NAME;
							// 01/15/2007   Assigned To field will always default to the current user. 
							else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "ASSIGNED_USER_ID" && rdr == null && !bIsPostBack )
							{
								// 01/29/2011   If Full Names have been enabled, then prepopulate with the full name. 
								if ( sDISPLAY_FIELD == "ASSIGNED_TO_NAME" )
									txtNAME.Text = Security.FULL_NAME;
								else
									txtNAME.Text = Security.USER_NAME;
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							txtNAME.Text = ex.Message;
						}
						HtmlInputHidden hidID = new HtmlInputHidden();
						tdField.Controls.Add(hidID);
						hidID.ID = sDATA_FIELD;
						try
						{
							if ( !bLayoutMode )
							{
								if ( !Sql.IsEmptyString(sDATA_FIELD) && rdr != null )
									hidID.Value = Sql.ToString(rdr[sDATA_FIELD]);
								// 11/25/2006   The team name should always default to the current user's private team. 
								// Make sure not to overwrite the value if this is a postback. 
								// The hidden field does not require the same viewstate fix as the txtNAME field. 
								// 04/23/2009   Make sure not to initialize the field with an empty guid as that will prevent the required field notice. 
								// 08/26/2009   Don't prepopulate team or user if in a search dialog. 
								else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "TEAM_ID" && rdr == null && !bIsPostBack && !Sql.IsEmptyGuid(Security.TEAM_ID) )
									hidID.Value = Security.TEAM_ID.ToString();
								// 01/15/2007   Assigned To field will always default to the current user. 
								else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "ASSIGNED_USER_ID" && rdr == null && !bIsPostBack )
									hidID.Value = Security.USER_ID.ToString();
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							txtNAME.Text = ex.Message;
						}
						//05/06/2010   Manually generate ClearModuleType so that it will be UpdatePanel safe. 
						// 07/27/2010   Add the ability to submit after clear. 
						if ( sDATA_LABEL == "PARENT_TYPE" && lstField != null )
							lstField.Attributes.Add("onChange", "ClearModuleType('', '" + hidID.ClientID + "', '" + txtNAME.ClientID + "', false);");
						
						Literal litNBSP = new Literal();
						tdField.Controls.Add(litNBSP);
						litNBSP.Text = "&nbsp;";
						
						// 06/20/2009   The Select button will go on a separate row in the NewRecord form. 
						if ( sLABEL_WIDTH == "100%" && sFIELD_WIDTH == "0%" && nDATA_COLUMNS == 1 )
						{
							nRowIndex++;
							trField = new HtmlTableRow();
							tbl.Rows.Insert(nRowIndex, trField);
							tdField = new HtmlTableCell();
							trField.Cells.Add(tdField);
						}
						HtmlInputButton btnChange = new HtmlInputButton("button");
						tdField.Controls.Add(btnChange);
						// 05/07/2006   Specify a name for the check button so that it can be referenced by SplendidTest. 
						btnChange.ID = sDATA_FIELD + "_btnChange";
						btnChange.Attributes.Add("class", "button");
						// 05/06/2010   Manually generate ParentPopup so that it will be UpdatePanel safe. 
						// 07/27/2010   Use the DATA_FORMAT field to determine if the ModulePopup will auto-submit. 
						string[] arrDATA_FORMAT = sDATA_FORMAT.Split(',');
						if ( lstField != null )
						{
							btnChange.Attributes.Add("onclick", "return ModulePopup(document.getElementById('" + lstField.ClientID + "').options[document.getElementById('" + lstField.ClientID + "').options.selectedIndex].value, '" + hidID.ClientID + "', '" + txtNAME.ClientID + "', null, " + (arrDATA_FORMAT[0] == "1" ? "true" : "false") + ", null);");
						}
						else if ( !Sql.IsEmptyString(sONCLICK_SCRIPT) )
							btnChange.Attributes.Add("onclick"  , sONCLICK_SCRIPT);
						// 03/31/2007   SugarCRM now uses Select instead of Change. 
						btnChange.Attributes.Add("title"    , L10n.Term(".LBL_SELECT_BUTTON_TITLE"));
						// 07/31/2006   Stop using VisualBasic library to increase compatibility with Mono. 
						// 03/31/2007   Stop using AccessKey for change button. 
						//btnChange.Attributes.Add("accessKey", L10n.Term(".LBL_SELECT_BUTTON_KEY").Substring(0, 1));
						btnChange.Value = L10n.Term(".LBL_SELECT_BUTTON_LABEL");
						// 01/18/2010   Apply ACL Field Security. 
						btnChange.Visible  =   bLayoutMode || bIsReadable;
						btnChange.Disabled = !(bLayoutMode || bIsWriteable);

						// 12/03/2007   Also create a Clear button. 
						// 05/06/2010   A Parent Type will always have a clear button. 
						if ( sONCLICK_SCRIPT.IndexOf("Popup();") > 0 || sDATA_LABEL == "PARENT_TYPE" )
						{
							litNBSP = new Literal();
							tdField.Controls.Add(litNBSP);
							litNBSP.Text = "&nbsp;";
							
							HtmlInputButton btnClear = new HtmlInputButton("button");
							tdField.Controls.Add(btnClear);
							btnClear.ID = sDATA_FIELD + "_btnClear";
							btnClear.Attributes.Add("class", "button");
							// 05/06/2010   Manually generate ClearModuleType so that it will be UpdatePanel safe. 
							// 07/27/2010   Add the ability to submit after clear. 
							btnClear.Attributes.Add("onclick"  , "return ClearModuleType('', '" + hidID.ClientID + "', '" + txtNAME.ClientID + "', " + (arrDATA_FORMAT[0] == "1" ? "true" : "false") + ");");
							btnClear.Attributes.Add("title"    , L10n.Term(".LBL_CLEAR_BUTTON_TITLE"));
							btnClear.Value = L10n.Term(".LBL_CLEAR_BUTTON_LABEL");
							// 01/18/2010   Apply ACL Field Security. 
							btnClear.Visible  =   bLayoutMode || bIsReadable;
							btnClear.Disabled = !(bLayoutMode || bIsWriteable);
						}
						// 11/11/2010   Always create the Required Field Validator so that we can Enable/Disable in a Rule. 
						if ( !bLayoutMode && /* bUI_REQUIRED && */ !Sql.IsEmptyString(sDATA_FIELD) )
						{
							RequiredFieldValidatorForHiddenInputs reqID = new RequiredFieldValidatorForHiddenInputs();
							reqID.ID                 = sDATA_FIELD + "_REQUIRED";
							reqID.ControlToValidate  = hidID.ID;
							reqID.ErrorMessage       = L10n.Term(".ERR_REQUIRED_FIELD");
							reqID.CssClass           = "required";
							reqID.EnableViewState    = false;
							// 01/16/2006   We don't enable required fields until we attempt to save. 
							// This is to allow unrelated form actions; the Cancel button is a good example. 
							reqID.EnableClientScript = false;
							reqID.Enabled            = false;
							// 02/21/2008   Add a little padding. 
							reqID.Style.Add("padding-left", "4px");
							tdField.Controls.Add(reqID);
						}
					}
				}
				// 05/17/2009   Add support for a generic module popup. 
				else if ( String.Compare(sFIELD_TYPE, "ModulePopup", true) == 0 )
				{
					//12/07/2009   For cell phones that do not support popups, convert to a DropDownList. 
					if ( !Sql.IsEmptyString(sDATA_FIELD) && !bSupportsPopups )
					{
						ListControl lstField = new DropDownList();
						tdField.Controls.Add(lstField);
						lstField.ID       = sDATA_FIELD;
						lstField.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						lstField.Visible  = bLayoutMode || bIsReadable;
						lstField.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							// 12/04/2005   Don't populate list if this is a post back. 
							if ( (bLayoutMode || !bIsPostBack) )
							{
								try
								{
									using ( DataTable dt = Crm.Modules.Items(sMODULE_TYPE) )
									{
										lstField.DataValueField = "ID"  ;
										lstField.DataTextField  = "NAME";
										lstField.DataSource     = dt;
										lstField.DataBind();
									}
								}
								catch(Exception ex)
								{
									SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);
								}
								if ( !bUI_REQUIRED )
								{
									lstField.Items.Insert(0, new ListItem(L10n.Term(".LBL_NONE"), ""));
									// 12/02/2007   AppendEditViewFields should be called inside Page_Load when not a postback, 
									// and in InitializeComponent when it is a postback. If done wrong, 
									// the page will bind after the list is populated, causing the list to populate again. 
									// This event will cause the NONE entry to be cleared.  Add a handler to catch this problem, 
									// but the real solution is to call AppendEditViewFields at the appropriate times based on the postback event. 
									lstField.DataBound += new EventHandler(ListControl_DataBound_AllowNull);
								}
							}
							if ( rdr != null )
							{
								// 08/19/2010   Check the list before assigning the value. 
								Utils.SetValue(lstField, Sql.ToGuid(rdr[sDATA_FIELD]).ToString());
							}
							else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "ASSIGNED_USER_ID" && rdr == null && !bIsPostBack )
							{
								// 08/19/2010   Check the list before assigning the value. 
								Utils.SetValue(lstField, Security.USER_ID.ToString());
							}
							else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "TEAM_ID" && rdr == null && !bIsPostBack )
							{
								// 08/19/2010   Check the list before assigning the value. 
								Utils.SetValue(lstField, Security.TEAM_ID.ToString());
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
					else if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						TextBox txtNAME = new TextBox();
						tdField.Controls.Add(txtNAME);
						// 10/05/2010   A custom field will not have a display field, but we still want to be able to access by name. 
						txtNAME.ID       = Sql.IsEmptyString(sDISPLAY_FIELD) ? sDATA_FIELD + "_NAME" : sDISPLAY_FIELD;
						txtNAME.ReadOnly = true;
						txtNAME.TabIndex = nFORMAT_TAB_INDEX;
						// 11/25/2006    Turn off viewstate so that we can fix the text on postback. 
						txtNAME.EnableViewState = false;
						// 01/18/2010   Apply ACL Field Security. 
						txtNAME.Visible  = bLayoutMode || bIsReadable;
						txtNAME.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							if ( bLayoutMode )
							{
								txtNAME.Text    = sDISPLAY_FIELD;
								txtNAME.Enabled = false         ;
							}
							// 11/25/2006   The Change text field is losing its value during a postback error. 
							else if ( bIsPostBack )
							{
								// 11/25/2006   In order for this posback fix to work, viewstate must be disabled for this field. 
								if ( tbl.Page.Request[txtNAME.UniqueID] != null )
									txtNAME.Text = Sql.ToString(tbl.Page.Request[txtNAME.UniqueID]);
							}
							else if ( rdr != null )
							{
								// 12/03/2009   We must use vwSchema to look for the desired column name. 
								// 11/22/2010   Convert data reader to data table for Rules Wizard. 
								//if ( vwSchema != null )
								//	vwSchema.RowFilter = "ColumnName = '" + Sql.EscapeSQL(sDISPLAY_FIELD) + "'";
								if ( !Sql.IsEmptyString(sDISPLAY_FIELD) && row != null && rdr.Table.Columns.Contains(sDISPLAY_FIELD) )
									txtNAME.Text = Sql.ToString(rdr[sDISPLAY_FIELD]);
								else
								{
									// 02/16/2010   Move ToGuid to the function so that it can be captured if invalid. 
									txtNAME.Text = Crm.Modules.ItemName(Application, sMODULE_TYPE, rdr[sDATA_FIELD]);
								}
							}
							// 11/25/2006   The team name should always default to the current user's private team. 
							// Make sure not to overwrite the value if this is a postback. 
							// 08/26/2009   Don't prepopulate team or user if in a search dialog. 
							else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "TEAM_ID" && rdr == null && !bIsPostBack )
								txtNAME.Text = Security.TEAM_NAME;
							// 01/15/2007   Assigned To field will always default to the current user. 
							else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "ASSIGNED_USER_ID" && rdr == null && !bIsPostBack )
							{
								// 01/29/2011   If Full Names have been enabled, then prepopulate with the full name. 
								if ( sDISPLAY_FIELD == "ASSIGNED_TO_NAME" )
									txtNAME.Text = Security.FULL_NAME;
								else
									txtNAME.Text = Security.USER_NAME;
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							txtNAME.Text = ex.Message;
						}
						HtmlInputHidden hidID = new HtmlInputHidden();
						tdField.Controls.Add(hidID);
						hidID.ID = sDATA_FIELD;
						try
						{
							if ( !bLayoutMode )
							{
								if ( !Sql.IsEmptyString(sDATA_FIELD) && rdr != null )
									hidID.Value = Sql.ToString(rdr[sDATA_FIELD]);
								// 11/25/2006   The team name should always default to the current user's private team. 
								// Make sure not to overwrite the value if this is a postback. 
								// The hidden field does not require the same viewstate fix as the txtNAME field. 
								// 04/23/2009   Make sure not to initialize the field with an empty guid as that will prevent the required field notice. 
								// 08/26/2009   Don't prepopulate team or user if in a search dialog. 
								else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "TEAM_ID" && rdr == null && !bIsPostBack && !Sql.IsEmptyGuid(Security.TEAM_ID) )
									hidID.Value = Security.TEAM_ID.ToString();
								// 01/15/2007   Assigned To field will always default to the current user. 
								else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "ASSIGNED_USER_ID" && rdr == null && !bIsPostBack )
									hidID.Value = Security.USER_ID.ToString();
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							txtNAME.Text = ex.Message;
						}
						
						Literal litNBSP = new Literal();
						tdField.Controls.Add(litNBSP);
						litNBSP.Text = "&nbsp;";
						
						// 06/20/2009   The Select button will go on a separate row in the NewRecord form. 
						if ( sLABEL_WIDTH == "100%" && sFIELD_WIDTH == "0%" && nDATA_COLUMNS == 1 )
						{
							nRowIndex++;
							trField = new HtmlTableRow();
							tbl.Rows.Insert(nRowIndex, trField);
							tdField = new HtmlTableCell();
							trField.Cells.Add(tdField);
						}
						HtmlInputButton btnChange = new HtmlInputButton("button");
						tdField.Controls.Add(btnChange);
						// 05/07/2006   Specify a name for the check button so that it can be referenced by SplendidTest. 
						btnChange.ID = sDATA_FIELD + "_btnChange";
						btnChange.Attributes.Add("class", "button");
						// 07/27/2010   We need to allow an onclick to override the default ModulePopup behavior. 
						string[] arrDATA_FORMAT = sDATA_FORMAT.Split(',');
						if ( !Sql.IsEmptyString(sONCLICK_SCRIPT) )
							btnChange.Attributes.Add("onclick"  , sONCLICK_SCRIPT);
						else
						{
							// 08/01/2010   We need to tell the Users popup to return the FULL NAME. 
							string sQUERY = "null";
							if ( sMODULE_TYPE == "Users" && sDISPLAY_FIELD == "ASSIGNED_TO_NAME" )
								sQUERY = "'FULL_NAME=1'";  // 08/01/201   Query must be quoted. 
							// 07/27/2010   Use the DATA_FORMAT field to determine if the ModulePopup will auto-submit. 
							btnChange.Attributes.Add("onclick"  , "return ModulePopup('" + sMODULE_TYPE + "', '" + hidID.ClientID + "', '" + txtNAME.ClientID + "', " + sQUERY + ", " + (arrDATA_FORMAT[0] == "1" ? "true" : "false") + ", null);");
						}
						// 03/31/2007   SugarCRM now uses Select instead of Change. 
						btnChange.Attributes.Add("title"    , L10n.Term(".LBL_SELECT_BUTTON_TITLE"));
						btnChange.Value = L10n.Term(".LBL_SELECT_BUTTON_LABEL");
						// 01/18/2010   Apply ACL Field Security. 
						btnChange.Visible  =   bLayoutMode || bIsReadable;
						btnChange.Disabled = !(bLayoutMode || bIsWriteable);
						
						litNBSP = new Literal();
						tdField.Controls.Add(litNBSP);
						litNBSP.Text = "&nbsp;";
						
						HtmlInputButton btnClear = new HtmlInputButton("button");
						tdField.Controls.Add(btnClear);
						btnClear.ID = sDATA_FIELD + "_btnClear";
						btnClear.Attributes.Add("class", "button");
						// 07/27/2010   Add the ability to submit after clear. 
						btnClear.Attributes.Add("onclick"  , "return ClearModuleType('" + sMODULE_TYPE + "', '" + hidID.ClientID + "', '" + txtNAME.ClientID + "', " + (arrDATA_FORMAT[0] == "1" ? "true" : "false") + ");");
						btnClear.Attributes.Add("title"    , L10n.Term(".LBL_CLEAR_BUTTON_TITLE"));
						btnClear.Value = L10n.Term(".LBL_CLEAR_BUTTON_LABEL");
						// 01/18/2010   Apply ACL Field Security. 
						btnClear.Visible  =   bLayoutMode || bIsReadable;
						btnClear.Disabled = !(bLayoutMode || bIsWriteable);
						
						// 11/11/2010   Always create the Required Field Validator so that we can Enable/Disable in a Rule. 
						if ( !bLayoutMode && /* bUI_REQUIRED && */ !Sql.IsEmptyString(sDATA_FIELD) )
						{
							RequiredFieldValidatorForHiddenInputs reqID = new RequiredFieldValidatorForHiddenInputs();
							reqID.ID                 = sDATA_FIELD + "_REQUIRED";
							reqID.ControlToValidate  = hidID.ID;
							reqID.ErrorMessage       = L10n.Term(".ERR_REQUIRED_FIELD");
							reqID.CssClass           = "required";
							reqID.EnableViewState    = false;
							// 01/16/2006   We don't enable required fields until we attempt to save. 
							// This is to allow unrelated form actions; the Cancel button is a good example. 
							reqID.EnableClientScript = false;
							reqID.Enabled            = false;
							// 02/21/2008   Add a little padding. 
							reqID.Style.Add("padding-left", "4px");
							tdField.Controls.Add(reqID);
						}
						// 11/23/2009   Allow AJAX AutoComplete to be turned off. 
						// 01/18/2010   AutoComplete only applies if the field is Writeable. 
						if ( bAjaxAutoComplete && !bLayoutMode && mgrAjax != null && !Sql.IsEmptyString(sMODULE_TYPE) && bIsWriteable )
						{
							string sTABLE_NAME    = Sql.ToString(Application["Modules." + sMODULE_TYPE + ".TableName"   ]);
							string sRELATIVE_PATH = Sql.ToString(Application["Modules." + sMODULE_TYPE + ".RelativePath"]);
							
							// 09/03/2009   File IO is expensive, so cache the results of the Exists test. 
							// 11/19/2009   Simplify the exists test. 
							// 03/03/2010   AutoComplete will not work if the DISPLAY_FIELD is not provided. 
							// 09/08/2010   sRELATIVE_PATH must be valid. 
							// 08/25/2013   File IO is slow, so cache existance test. 
							if ( !Sql.IsEmptyString(sDISPLAY_FIELD) && !Sql.IsEmptyString(sRELATIVE_PATH) && Utils.CachedFileExists(HttpContext.Current, sRELATIVE_PATH + "AutoComplete.asmx") )
							{
								// 09/03/2009   If the AutoComplete file exists, then we can safely diable the ReadOnly flag. 
								txtNAME.ReadOnly = false;
								txtNAME.Attributes.Add("onblur", sTABLE_NAME + "_" + txtNAME.ID + "_Changed(this);");
								// 09/03/2009   Add a PREV_ field so that we can detect a text change. 
								HtmlInputHidden hidPREVIOUS = new HtmlInputHidden();
								tdField.Controls.Add(hidPREVIOUS);
								hidPREVIOUS.ID = "PREV_" + sDISPLAY_FIELD;
								try
								{
									if ( !bLayoutMode )
									{
										if ( !Sql.IsEmptyString(sDISPLAY_FIELD) && rdr != null )
											hidPREVIOUS.Value = Sql.ToString(rdr[sDISPLAY_FIELD]);
										else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "TEAM_ID" && rdr == null && !bIsPostBack )
											hidPREVIOUS.Value = Security.TEAM_NAME;
										else if ( sEDIT_NAME.IndexOf(".Search") < 0 && sDATA_FIELD == "ASSIGNED_USER_ID" && rdr == null && !bIsPostBack )
										{
											// 01/29/2011   If Full Names have been enabled, then prepopulate with the full name. 
											if ( sDISPLAY_FIELD == "ASSIGNED_TO_NAME" )
												hidPREVIOUS.Value = Security.FULL_NAME;
											else
												hidPREVIOUS.Value = Security.USER_NAME;
										}
									}
								}
								catch(Exception ex)
								{
									SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
								}
								
								AjaxControlToolkit.AutoCompleteExtender auto = new AjaxControlToolkit.AutoCompleteExtender();
								tdField.Controls.Add(auto);
								auto.ID                   = "auto" + txtNAME.ID;
								auto.TargetControlID      = txtNAME.ID;
								auto.ServiceMethod        = sTABLE_NAME + "_" + txtNAME.ID + "_" + "List";
								auto.ServicePath          = sRELATIVE_PATH + "AutoComplete.asmx";
								auto.MinimumPrefixLength  = 2;
								auto.CompletionInterval   = 250;
								auto.EnableCaching        = true;
								// 12/09/2010   Provide a way to customize the AutoComplete.CompletionSetCount. 
								auto.CompletionSetCount   = Crm.Config.CompletionSetCount();
								// 07/27/2010   We need to use the ContextKey feature of AutoComplete to pass the Account Name to the Contact function. 
								// 07/27/2010   JavaScript seems to have a problem with function overloading. 
								// Instead of trying to use function overloading, use a DataFormat flag to check the UseContextKey AutoComplete flag. 
								if ( arrDATA_FORMAT.Length > 1 && arrDATA_FORMAT[1] == "1" )
									auto.UseContextKey = true;
								
								ServiceReference svc = new ServiceReference(sRELATIVE_PATH + "AutoComplete.asmx");
								ScriptReference  scr = new ScriptReference (sRELATIVE_PATH + "AutoComplete.js"  );
								if ( !mgrAjax.Services.Contains(svc) )
									mgrAjax.Services.Add(svc);
								if ( !mgrAjax.Scripts.Contains(scr) )
									mgrAjax.Scripts.Add(scr);
								
								litNBSP = new Literal();
								tdField.Controls.Add(litNBSP);
								litNBSP.Text = "&nbsp;";
								// 09/03/2009   We need to use a unique ID for each ajax error, 
								// otherwise we will not place the error message in the correct location. 
								HtmlGenericControl spnAjaxErrors = new HtmlGenericControl("span");
								tdField.Controls.Add(spnAjaxErrors);
								// 09/03/2009   Don't include the table name in the AjaxErrors field so that 
								// it can be cleared from the ChangeModule() module popup script. 
								spnAjaxErrors.ID = txtNAME.ID + "_AjaxErrors";
								spnAjaxErrors.Attributes.Add("style", "color:Red");
								spnAjaxErrors.EnableViewState = false;
							}
						}
						// 10/20/2010   Automatically associate the TextBox with a Submit button. 
						// 10/20/2010   We are still having a problem with the Enter Key hijacking the Auto-Complete logic. The most practical solution is to block the Enter Key. 
						if ( !bLayoutMode && !Sql.IsEmptyString(sSubmitClientID) )
						{
							if ( mgrAjax != null )
							{
								ScriptManager.RegisterStartupScript(Page, typeof(System.String), txtNAME.ClientID + "_EnterKey", Utils.PreventEnterKeyPress(txtNAME.ClientID), false);
							}
							else
							{
								#pragma warning disable 618
								Page.ClientScript.RegisterStartupScript(typeof(System.String), txtNAME.ClientID + "_EnterKey", Utils.PreventEnterKeyPress(txtNAME.ClientID));
								#pragma warning restore 618
							}
						}
					}
				}
				// 09/02/2009   Add AJAX AutoCompletion
				else if ( String.Compare(sFIELD_TYPE, "ModuleAutoComplete", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						TextBox txtField = new TextBox();
						tdField.Controls.Add(txtField);
						txtField.ID       = sDATA_FIELD;
						txtField.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						txtField.Visible  = bLayoutMode || bIsReadable;
						txtField.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							txtField.MaxLength = nFORMAT_MAX_LENGTH   ;
							// 06/20/2009   The NewRecord forms do not specify a size. 
							if ( nFORMAT_SIZE > 0 )
								txtField.Attributes.Add("size", nFORMAT_SIZE.ToString());
							txtField.TextMode  = TextBoxMode.SingleLine;
							// 08/31/2012   Apple and Android devices should support speech and handwriting. 
							// Speech does not work on text areas, only add to single line text boxes. 
							if ( Utils.SupportsSpeech && Sql.ToBoolean(Application["CONFIG.enable_speech"]) )
							{
								txtField.Attributes.Add("speech", "speech");
								txtField.Attributes.Add("x-webkit-speech", "x-webkit-speech");
							}
							if ( bLayoutMode )
							{
								txtField.Text    = sDATA_FIELD;
								txtField.Enabled = false         ;
							}
							else if ( !Sql.IsEmptyString(sDATA_FIELD) && rdr != null )
								txtField.Text = Sql.ToString(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							txtField.Text = ex.Message;
						}
						// 11/23/2009   Allow AJAX AutoComplete to be turned off. 
						// 01/18/2010   AutoComplete only applies if the field is Writeable. 
						if ( bAjaxAutoComplete && !bLayoutMode && mgrAjax != null && !Sql.IsEmptyString(sMODULE_TYPE) && bIsWriteable )
						{
							string sTABLE_NAME    = Sql.ToString(Application["Modules." + sMODULE_TYPE + ".TableName"   ]);
							string sRELATIVE_PATH = Sql.ToString(Application["Modules." + sMODULE_TYPE + ".RelativePath"]);
							
							// 09/03/2009   File IO is expensive, so cache the results of the Exists test. 
							// 11/19/2009   Simplify the exists test. 
							// 09/08/2010   sRELATIVE_PATH must be valid. 
							// 08/25/2013   File IO is slow, so cache existance test. 
							if ( !Sql.IsEmptyString(sRELATIVE_PATH) && Utils.CachedFileExists(HttpContext.Current, sRELATIVE_PATH + "AutoComplete.asmx") )
							{
								AjaxControlToolkit.AutoCompleteExtender auto = new AjaxControlToolkit.AutoCompleteExtender();
								tdField.Controls.Add(auto);
								auto.ID                   = "auto" + txtField.ID;
								auto.TargetControlID      = txtField.ID;
								auto.ServiceMethod        = sTABLE_NAME + "_" + txtField.ID + "_" + "List";
								auto.ServicePath          = sRELATIVE_PATH + "AutoComplete.asmx";
								auto.MinimumPrefixLength  = 2;
								auto.CompletionInterval   = 250;
								auto.EnableCaching        = true;
								// 12/09/2010   Provide a way to customize the AutoComplete.CompletionSetCount. 
								auto.CompletionSetCount   = Crm.Config.CompletionSetCount();
								
								ServiceReference svc = new ServiceReference(sRELATIVE_PATH + "AutoComplete.asmx");
								ScriptReference  scr = new ScriptReference (sRELATIVE_PATH + "AutoComplete.js"  );
								if ( !mgrAjax.Services.Contains(svc) )
									mgrAjax.Services.Add(svc);
								if ( !mgrAjax.Scripts.Contains(scr) )
									mgrAjax.Scripts.Add(scr);
							}
							else
							{
								Application["Exists." + sRELATIVE_PATH + "AutoComplete.asmx"] = false;
							}
						}
						// 06/21/2009   Automatically associate the TextBox with a Submit button. 
						if ( !bLayoutMode && !Sql.IsEmptyString(sSubmitClientID) )
						{
							if ( mgrAjax != null )
							{
								// 06/21/2009   The name of the script block must be unique for each instance of this control. 
								// 06/21/2009   Use RegisterStartupScript instead of RegisterClientScriptBlock so that the script will run after the control has been created. 
								ScriptManager.RegisterStartupScript(Page, typeof(System.String), txtField.ClientID + "_EnterKey", Utils.RegisterEnterKeyPress(txtField.ClientID, sSubmitClientID), false);
							}
							else
							{
								#pragma warning disable 618
								Page.ClientScript.RegisterStartupScript(typeof(System.String), txtField.ClientID + "_EnterKey", Utils.RegisterEnterKeyPress(txtField.ClientID, sSubmitClientID));
								#pragma warning restore 618
							}
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "TextBox", true) == 0 || String.Compare(sFIELD_TYPE, "Password", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						TextBox txtField = new TextBox();
						tdField.Controls.Add(txtField);
						txtField.ID       = sDATA_FIELD;
						txtField.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						txtField.Visible  = bLayoutMode || bIsReadable;
						txtField.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							if ( nFORMAT_ROWS > 0 && nFORMAT_COLUMNS > 0 )
							{
								txtField.Rows     = nFORMAT_ROWS   ;
								txtField.Columns  = nFORMAT_COLUMNS;
								txtField.TextMode = TextBoxMode.MultiLine;
								
								// 08/22/2012   Apple and Android devices should support speech and handwriting. 
								// Speech does not work on text areas, only add to single line text boxes. 
								// http://www.labnol.org/software/add-speech-recognition-to-website/19989/
								if ( Utils.SupportsSpeech && Sql.ToBoolean(Application["CONFIG.enable_speech"]) )
								{
									TextBox txtSpeech = new TextBox();
									tdField.Controls.Add(txtSpeech);
									txtSpeech.ID       = sDATA_FIELD + "_SPEECH";
									txtSpeech.TabIndex = nFORMAT_TAB_INDEX;
									txtSpeech.Visible  = bLayoutMode || bIsReadable;
									txtSpeech.Enabled  = bLayoutMode || bIsWriteable;
									txtSpeech.Attributes.Add("style", "width: 15px; height: 20px; border: 0px; background-color: transparent; vertical-align:top;");
									txtSpeech.Attributes.Add("speech", "speech");
									txtSpeech.Attributes.Add("x-webkit-speech", "x-webkit-speech");
									txtSpeech.Attributes.Add("onspeechchange"      , "SpeechTranscribe('" + txtSpeech.ClientID + "', '" + txtField.ClientID + "');");
									txtSpeech.Attributes.Add("onwebkitspeechchange", "SpeechTranscribe('" + txtSpeech.ClientID + "', '" + txtField.ClientID + "');");
								}
							}
							else
							{
								txtField.MaxLength = nFORMAT_MAX_LENGTH   ;
								// 06/20/2009   The NewRecord forms do not specify a size. 
								if ( nFORMAT_SIZE > 0 )
									txtField.Attributes.Add("size", nFORMAT_SIZE.ToString());
								txtField.TextMode  = TextBoxMode.SingleLine;
								// 08/22/2012   Apple and Android devices should support speech and handwriting. 
								// Speech does not work on text areas, only add to single line text boxes. 
								// 08/31/2012  Exclude speech from Password fields. 
								if ( String.Compare(sFIELD_TYPE, "TextBox", true) == 0 && Utils.SupportsSpeech && Sql.ToBoolean(Application["CONFIG.enable_speech"]) )
								{
									txtField.Attributes.Add("speech", "speech");
									txtField.Attributes.Add("x-webkit-speech", "x-webkit-speech");
								}
							}
							if ( bLayoutMode )
							{
								txtField.Text     = sDATA_FIELD;
								txtField.ReadOnly = true       ;
							}
							else if ( !Sql.IsEmptyString(sDATA_FIELD) && rdr != null )
							{
								// 11/22/2010   Convert data reader to data table for Rules Wizard. 
								// 11/22/2010   There is no way to get the DbType from a DataTable/DataRow, so just rely upon the detection of Decimal. 
								//int    nOrdinal  = rdr.GetOrdinal(sDATA_FIELD);
								string sTypeName = String.Empty;  // rdr.GetDataTypeName(nOrdinal);
								Type tDATA_FIELD = rdr[sDATA_FIELD].GetType();
								// 03/04/2006   Display currency in the proper format. 
								// Only SQL Server is likely to return the money type, so also include the decimal type. 
								if ( sTypeName == "money" || tDATA_FIELD == typeof(System.Decimal) )
								{
									if ( Sql.IsEmptyString(sDATA_FORMAT) )
										txtField.Text = Sql.ToDecimal(rdr[sDATA_FIELD]).ToString("#,##0.00");
									else
										txtField.Text = Sql.ToDecimal(rdr[sDATA_FIELD]).ToString(sDATA_FORMAT);
								}
								// 01/19/2010   Now that ProjectTask.ESTIMATED_EFFORT is a float, we need to format the value. 
								else if ( tDATA_FIELD == typeof(System.Double) )
								{
									if ( Sql.IsEmptyString(sDATA_FORMAT) )
										txtField.Text = Sql.ToDouble(rdr[sDATA_FIELD]).ToString("0.00");
									else
										txtField.Text = Sql.ToDouble(rdr[sDATA_FIELD]).ToString(sDATA_FORMAT);
								}
								else if ( tDATA_FIELD == typeof(System.Int32) )
								{
									if ( Sql.IsEmptyString(sDATA_FORMAT) )
										txtField.Text = Sql.ToInteger(rdr[sDATA_FIELD]).ToString("0");
									else
										txtField.Text = Sql.ToInteger(rdr[sDATA_FIELD]).ToString(sDATA_FORMAT);
								}
								else
									txtField.Text = Sql.ToString(rdr[sDATA_FIELD]);
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							txtField.Text = ex.Message;
						}
						if ( String.Compare(sFIELD_TYPE, "Password", true) == 0 )
							txtField.TextMode = TextBoxMode.Password;
						// 09/16/2012   Add onchange event to TextBox. 
						else if ( String.Compare(sFIELD_TYPE, "TextBox", true) == 0 && !bLayoutMode )
						{
							if ( !Sql.IsEmptyString(sONCLICK_SCRIPT) )
								txtField.Attributes.Add("onchange" , sONCLICK_SCRIPT);
						}
						// 06/21/2009   Automatically associate the TextBox with a Submit button. 
						if ( !bLayoutMode && !Sql.IsEmptyString(sSubmitClientID) )
						{
							if ( mgrAjax != null )
							{
								// 06/21/2009   The name of the script block must be unique for each instance of this control. 
								// 06/21/2009   Use RegisterStartupScript instead of RegisterClientScriptBlock so that the script will run after the control has been created. 
								ScriptManager.RegisterStartupScript(Page, typeof(System.String), txtField.ClientID + "_EnterKey", Utils.RegisterEnterKeyPress(txtField.ClientID, sSubmitClientID), false);
							}
							else
							{
								#pragma warning disable 618
								Page.ClientScript.RegisterStartupScript(typeof(System.String), txtField.ClientID + "_EnterKey", Utils.RegisterEnterKeyPress(txtField.ClientID, sSubmitClientID));
								#pragma warning restore 618
							}
						}
						// 11/11/2010   Always create the Required Field Validator so that we can Enable/Disable in a Rule. 
						if ( !bLayoutMode && /* bUI_REQUIRED && */ !Sql.IsEmptyString(sDATA_FIELD) )
						{
							RequiredFieldValidator reqNAME = new RequiredFieldValidator();
							reqNAME.ID                 = sDATA_FIELD + "_REQUIRED";
							reqNAME.ControlToValidate  = txtField.ID;
							reqNAME.ErrorMessage       = L10n.Term(".ERR_REQUIRED_FIELD");
							reqNAME.CssClass           = "required";
							reqNAME.EnableViewState    = false;
							// 01/16/2006   We don't enable required fields until we attempt to save. 
							// This is to allow unrelated form actions; the Cancel button is a good example. 
							reqNAME.EnableClientScript = false;
							reqNAME.Enabled            = false;
							reqNAME.Style.Add("padding-left", "4px");
							tdField.Controls.Add(reqNAME);
						}
						if ( !bLayoutMode && !Sql.IsEmptyString(sDATA_FIELD) )
						{
							// 01/18/2010   We only need to validate if the field is Writeable. 
							if ( sVALIDATION_TYPE == "RegularExpressionValidator" && !Sql.IsEmptyString(sREGULAR_EXPRESSION) && !Sql.IsEmptyString(sFIELD_VALIDATOR_MESSAGE) && bIsWriteable )
							{
								RegularExpressionValidator reqVALIDATOR = new RegularExpressionValidator();
								reqVALIDATOR.ID                   = sDATA_FIELD + "_VALIDATOR";
								reqVALIDATOR.ControlToValidate    = txtField.ID;
								reqVALIDATOR.ErrorMessage         = L10n.Term(sFIELD_VALIDATOR_MESSAGE);
								reqVALIDATOR.ValidationExpression = sREGULAR_EXPRESSION;
								reqVALIDATOR.CssClass             = "required";
								reqVALIDATOR.EnableViewState      = false;
								// 04/02/2008   We don't enable required fields until we attempt to save. 
								// This is to allow unrelated form actions; the Cancel button is a good example. 
								reqVALIDATOR.EnableClientScript   = false;
								reqVALIDATOR.Enabled              = false;
								reqVALIDATOR.Style.Add("padding-left", "4px");
								tdField.Controls.Add(reqVALIDATOR);
							}
						}
					}
				}
				// 04/02/2009   Add support for FCKEditor to the EditView. 
				else if ( String.Compare(sFIELD_TYPE, "HtmlEditor", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 09/18/2011   Upgrade to CKEditor 3.6.2. 
						CKEditorControl txtField = new CKEditorControl();
						tdField.Controls.Add(txtField);
						txtField.ID         = sDATA_FIELD;
						txtField.Toolbar    = "Taoqi";
						// 09/18/2011   Set the language for CKEditor. 
						txtField.Language   = L10n.NAME;
						txtField.BasePath   = "~/ckeditor/";
						// 04/26/2012   Add file uploader. 
						txtField.FilebrowserUploadUrl    = txtField.ResolveUrl("~/ckeditor/upload.aspx");
						txtField.FilebrowserBrowseUrl    = txtField.ResolveUrl("~/Images/Popup.aspx");
						//txtField.FilebrowserWindowWidth  = "640";
						//txtField.FilebrowserWindowHeight = "480";
						// 01/18/2010   Apply ACL Field Security. 
						txtField.Visible  = bLayoutMode || bIsReadable;
						try
						{
							if ( nFORMAT_ROWS > 0 && nFORMAT_COLUMNS > 0 )
							{
								txtField.Height = nFORMAT_ROWS   ;
								txtField.Width  = nFORMAT_COLUMNS;
							}
							if ( bLayoutMode )
							{
								txtField.Text     = sDATA_FIELD;
							}
							else if ( !Sql.IsEmptyString(sDATA_FIELD) && rdr != null )
							{
								txtField.Text = Sql.ToString(rdr[sDATA_FIELD]);
								// 01/18/2010   FCKEditor does not have an Enable field, so just hide and replace with a Literal control. 
								if ( bIsReadable && !bIsWriteable )
								{
									txtField.Visible = false;
									Literal litField = new Literal();
									litField.ID = sDATA_FIELD + "_ReadOnly";
									tdField.Controls.Add(litField);
									litField.Text = Sql.ToString(rdr[sDATA_FIELD]);
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							txtField.Text = ex.Message;
						}
						// 04/02/2009   The standard RequiredFieldValidator will not work on the FCKeditor. 
						/*
						if ( !bLayoutMode && bUI_REQUIRED && !Sql.IsEmptyString(sDATA_FIELD) )
						{
							RequiredFieldValidator reqNAME = new RequiredFieldValidator();
							reqNAME.ID                 = sDATA_FIELD + "_REQUIRED";
							reqNAME.ControlToValidate  = txtField.ID;
							reqNAME.ErrorMessage       = L10n.Term(".ERR_REQUIRED_FIELD");
							reqNAME.CssClass           = "required";
							reqNAME.EnableViewState    = false;
							// 01/16/2006   We don't enable required fields until we attempt to save. 
							// This is to allow unrelated form actions; the Cancel button is a good example. 
							reqNAME.EnableClientScript = false;
							reqNAME.Enabled            = false;
							reqNAME.Style.Add("padding-left", "4px");
							tdField.Controls.Add(reqNAME);
						}
						*/
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "DatePicker", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/03/2005   UserControls must be loaded. 
						DatePicker ctlDate = tbl.Page.LoadControl("~/_controls/DatePicker.ascx") as DatePicker;
						tdField.Controls.Add(ctlDate);
						ctlDate.ID = sDATA_FIELD;
						// 05/06/2010   Use a special Page flag to override the default IsPostBack behavior. 
						ctlDate.NotPostBack = bNotPostBack;
						// 05/10/2006   Set the tab index. 
						ctlDate.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						ctlDate.Visible  = bLayoutMode || bIsReadable;
						ctlDate.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							if ( rdr != null )
								ctlDate.Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						// 01/16/2006   We validate elsewhere. 
						/*
						if ( !bLayoutMode && bUI_REQUIRED && !Sql.IsEmptyString(sDATA_FIELD) )
						{
							ctlDate.Required = true;
						}
						*/
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "DateRange", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/17/2007   Use table to align before and after labels. 
						Table tblDateRange = new Table();
						tdField.Controls.Add(tblDateRange);
						TableRow trAfter = new TableRow();
						TableRow trBefore = new TableRow();
						tblDateRange.Rows.Add(trAfter);
						tblDateRange.Rows.Add(trBefore);
						TableCell tdAfterLabel  = new TableCell();
						TableCell tdAfterData   = new TableCell();
						TableCell tdBeforeLabel = new TableCell();
						TableCell tdBeforeData  = new TableCell();
						trAfter .Cells.Add(tdAfterLabel );
						trAfter .Cells.Add(tdAfterData  );
						trBefore.Cells.Add(tdBeforeLabel);
						trBefore.Cells.Add(tdBeforeData );

						// 12/03/2005   UserControls must be loaded. 
						DatePicker ctlDateStart = tbl.Page.LoadControl("~/_controls/DatePicker.ascx") as DatePicker;
						DatePicker ctlDateEnd   = tbl.Page.LoadControl("~/_controls/DatePicker.ascx") as DatePicker;
						Literal litAfterLabel  = new Literal();
						Literal litBeforeLabel = new Literal();
						litAfterLabel .Text = L10n.Term("SavedSearch.LBL_SEARCH_AFTER" );
						litBeforeLabel.Text = L10n.Term("SavedSearch.LBL_SEARCH_BEFORE");
						//tdField.Controls.Add(litAfterLabel );
						//tdField.Controls.Add(ctlDateStart  );
						//tdField.Controls.Add(litBeforeLabel);
						//tdField.Controls.Add(ctlDateEnd    );
						tdAfterLabel .Controls.Add(litAfterLabel );
						tdAfterData  .Controls.Add(ctlDateStart  );
						tdBeforeLabel.Controls.Add(litBeforeLabel);
						tdBeforeData .Controls.Add(ctlDateEnd    );

						ctlDateStart.ID = sDATA_FIELD + "_AFTER";
						ctlDateEnd  .ID = sDATA_FIELD + "_BEFORE";
						// 05/06/2010   Use a special Page flag to override the default IsPostBack behavior. 
						ctlDateStart.NotPostBack = bNotPostBack;
						ctlDateEnd  .NotPostBack = bNotPostBack;
						// 05/10/2006   Set the tab index. 
						ctlDateStart.TabIndex = nFORMAT_TAB_INDEX;
						ctlDateEnd  .TabIndex = nFORMAT_TAB_INDEX;

						// 01/18/2010   Apply ACL Field Security. 
						tblDateRange.Visible  = bLayoutMode || bIsReadable;
						ctlDateStart.Visible  = bLayoutMode || bIsReadable;
						ctlDateStart.Enabled  = bLayoutMode || bIsWriteable;
						// 01/18/2010   Apply ACL Field Security. 
						ctlDateEnd  .Visible  = bLayoutMode || bIsReadable;
						ctlDateEnd  .Enabled  = bLayoutMode || bIsWriteable;
						// 06/21/2009   Move SearchView EnterKey registration from SearchView.asx to here. 
						// 01/18/2010   Don't register the EnterKey unless the date is Writeable. 
						if ( !bLayoutMode && !Sql.IsEmptyString(sSubmitClientID) && bIsWriteable )
						{
							if ( mgrAjax != null )
							{
								// 06/21/2009   The name of the script block must be unique for each instance of this control. 
								// 06/21/2009   Use RegisterStartupScript instead of RegisterClientScriptBlock so that the script will run after the control has been created. 
								ScriptManager.RegisterStartupScript(Page, typeof(System.String), ctlDateStart.DateClientID + "_EnterKey", Utils.RegisterEnterKeyPress(ctlDateStart.DateClientID, sSubmitClientID), false);
								ScriptManager.RegisterStartupScript(Page, typeof(System.String), ctlDateEnd  .DateClientID + "_EnterKey", Utils.RegisterEnterKeyPress(ctlDateEnd  .DateClientID, sSubmitClientID), false);
							}
							else
							{
								#pragma warning disable 618
								Page.ClientScript.RegisterStartupScript(typeof(System.String), ctlDateStart.DateClientID + "_EnterKey", Utils.RegisterEnterKeyPress(ctlDateStart.DateClientID, sSubmitClientID));
								Page.ClientScript.RegisterStartupScript(typeof(System.String), ctlDateEnd  .DateClientID + "_EnterKey", Utils.RegisterEnterKeyPress(ctlDateEnd  .DateClientID, sSubmitClientID));
								#pragma warning restore 618
							}
						}
						try
						{
							if ( rdr != null )
							{
								ctlDateStart.Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
								ctlDateEnd  .Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						// 01/16/2006   We validate elsewhere. 
						/*
						if ( !bLayoutMode && bUI_REQUIRED && !Sql.IsEmptyString(sDATA_FIELD) )
						{
							ctlDateStart.Required = true;
							ctlDateEnd  .Required = true;
						}
						*/
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "DateTimePicker", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/03/2005   UserControls must be loaded. 
						DateTimePicker ctlDate = tbl.Page.LoadControl("~/_controls/DateTimePicker.ascx") as DateTimePicker;
						tdField.Controls.Add(ctlDate);
						ctlDate.ID = sDATA_FIELD;
						// 05/06/2010   Use a special Page flag to override the default IsPostBack behavior. 
						ctlDate.NotPostBack = bNotPostBack;
						// 05/10/2006   Set the tab index. 
						ctlDate.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						ctlDate.Visible  = bLayoutMode || bIsReadable;
						ctlDate.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							if ( rdr != null )
								ctlDate.Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "DateTimeEdit", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/03/2005   UserControls must be loaded. 
						DateTimeEdit ctlDate = tbl.Page.LoadControl("~/_controls/DateTimeEdit.ascx") as DateTimeEdit;
						tdField.Controls.Add(ctlDate);
						ctlDate.ID = sDATA_FIELD;
						// 05/06/2010   Use a special Page flag to override the default IsPostBack behavior. 
						ctlDate.NotPostBack = bNotPostBack;
						// 05/10/2006   Set the tab index. 
						ctlDate.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						ctlDate.Visible  = bLayoutMode || bIsReadable;
						ctlDate.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							if ( rdr != null )
								ctlDate.Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( !bLayoutMode && bUI_REQUIRED )
						{
							ctlDate.EnableNone = false;
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				// 06/20/2009   Add DateTimeNewRecord so that the NewRecord forms can use the Dynamic rendering. 
				else if ( String.Compare(sFIELD_TYPE, "DateTimeNewRecord", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/03/2005   UserControls must be loaded. 
						DateTimeEdit ctlDate = tbl.Page.LoadControl("~/_controls/DateTimeNewRecord.ascx") as DateTimeEdit;
						tdField.Controls.Add(ctlDate);
						ctlDate.ID = sDATA_FIELD;
						// 05/06/2010   Use a special Page flag to override the default IsPostBack behavior. 
						ctlDate.NotPostBack = bNotPostBack;
						// 05/10/2006   Set the tab index. 
						ctlDate.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						ctlDate.Visible  = bLayoutMode || bIsReadable;
						ctlDate.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							if ( rdr != null )
								ctlDate.Value = T10n.FromServerTime(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( !bLayoutMode && bUI_REQUIRED )
						{
							ctlDate.EnableNone = false;
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "File", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						HtmlInputHidden ctlHidden = null;
						if ( !bLayoutMode )
						{
							HtmlInputFile ctlField = new HtmlInputFile();
							tdField.Controls.Add(ctlField);
							// 04/17/2006   The image needs to reference the file control. 
							// 11/25/2010   Appending _File breaks the previous behavior of Notes, Bugs and Documents.
							// 11/25/2010   The file field is special in that it may not exist as a table column. 
							// 12/01/2010   rdr will not be available during postback, so we cannot use it do determine the field name. 
							// 12/01/2010   The only solution is to fix the naming convention for Notes, Bugs and Documents. 
							//if ( rdr != null && rdr.Table.Columns.Contains(sDATA_FIELD) )
							{
								ctlField.ID = sDATA_FIELD + "_File";
								ctlHidden = new HtmlInputHidden();
								tdField.Controls.Add(ctlHidden);
								ctlHidden.ID = sDATA_FIELD;
							}
							//else
							//{
							//	ctlField.ID = sDATA_FIELD;
							//}
							ctlField.MaxLength = nFORMAT_MAX_LENGTH;
							ctlField.Size      = nFORMAT_SIZE;
							ctlField.Attributes.Add("TabIndex", nFORMAT_TAB_INDEX.ToString());
							// 01/18/2010   Apply ACL Field Security. 
							ctlField.Visible  =   bLayoutMode || bIsReadable;
							ctlField.Disabled = !(bLayoutMode || bIsWriteable);

							Literal litBR = new Literal();
							litBR.Text = "<br />";
							tdField.Controls.Add(litBR);

							// 11/11/2010   Always create the Required Field Validator so that we can Enable/Disable in a Rule. 
							if ( !bLayoutMode /* && bUI_REQUIRED */ )
							{
								RequiredFieldValidator reqNAME = new RequiredFieldValidator();
								reqNAME.ID                 = sDATA_FIELD + "_REQUIRED";
								reqNAME.ControlToValidate  = ctlField.ID;
								reqNAME.ErrorMessage       = L10n.Term(".ERR_REQUIRED_FIELD");
								reqNAME.CssClass           = "required";
								reqNAME.EnableViewState    = false;
								// 01/16/2006   We don't enable required fields until we attempt to save. 
								// This is to allow unrelated form actions; the Cancel button is a good example. 
								reqNAME.EnableClientScript = false;
								reqNAME.Enabled            = false;
								reqNAME.Style.Add("padding-left", "4px");
								tdField.Controls.Add(reqNAME);
							}
						}
						
						// 11/23/2010   File needs to act like an Image. 
						HyperLink lnkField = new HyperLink();
						// 04/13/2006   Give the image a name so that it can be validated with SplendidTest. 
						lnkField.ID = "lnk" + sDATA_FIELD;
						// 01/18/2010   Apply ACL Field Security. 
						lnkField.Visible  = bLayoutMode || bIsReadable;
						try
						{
							if ( bLayoutMode )
							{
								Literal litField = new Literal();
								litField.Text = sDATA_FIELD;
								tdField.Controls.Add(litField);
							}
							else if ( rdr != null && rdr.Table.Columns.Contains(sDATA_FIELD) )
							{
								// 11/25/2010   The file field is special in that it may not exist as a table column. 
								if ( ctlHidden != null && !Sql.IsEmptyString(rdr[sDATA_FIELD]) )
								{
									ctlHidden.Value = Sql.ToString(rdr[sDATA_FIELD]);
									lnkField.NavigateUrl = "~/Images/Image.aspx?ID=" + ctlHidden.Value;
									lnkField.Text = Crm.Modules.ItemName(Application, "Images", ctlHidden.Value);
									// 04/13/2006   Only add the image if it exists. 
									tdField.Controls.Add(lnkField);
									
									// 04/17/2006   Provide a clear button. 
									Literal litClear = new Literal();
									litClear.Text = "&nbsp; <input type=\"button\" class=\"button\" onclick=\"document.getElementById('" + ctlHidden.ClientID + "').value='';document.getElementById('" + lnkField.ClientID + "').innerHTML='';" + "\"  value='" + "  " + L10n.Term(".LBL_CLEAR_BUTTON_LABEL" ) + "  " + "' title='" + L10n.Term(".LBL_CLEAR_BUTTON_TITLE" ) + "' />";
									tdField.Controls.Add(litClear);
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							Literal litField = new Literal();
							litField.Text = ex.Message;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "Image", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						HtmlInputHidden ctlHidden = new HtmlInputHidden();
						if ( !bLayoutMode )
						{
							tdField.Controls.Add(ctlHidden);
							ctlHidden.ID = sDATA_FIELD;

							HtmlInputFile ctlField = new HtmlInputFile();
							tdField.Controls.Add(ctlField);
							// 04/17/2006   The image needs to reference the file control. 
							ctlField.ID = sDATA_FIELD + "_File";
							ctlField.MaxLength = nFORMAT_MAX_LENGTH;
							ctlField.Size      = nFORMAT_SIZE;
							ctlField.Attributes.Add("TabIndex", nFORMAT_TAB_INDEX.ToString());
							// 01/18/2010   Apply ACL Field Security. 
							ctlField.Visible  =   bLayoutMode || bIsReadable;
							ctlField.Disabled = !(bLayoutMode || bIsWriteable);

							Literal litBR = new Literal();
							litBR.Text = "<br />";
							tdField.Controls.Add(litBR);

							// 11/25/2010   Add required field validator. 
							if ( !bLayoutMode /* && bUI_REQUIRED */ )
							{
								RequiredFieldValidator reqNAME = new RequiredFieldValidator();
								reqNAME.ID                 = sDATA_FIELD + "_REQUIRED";
								reqNAME.ControlToValidate  = ctlField.ID;
								reqNAME.ErrorMessage       = L10n.Term(".ERR_REQUIRED_FIELD");
								reqNAME.CssClass           = "required";
								reqNAME.EnableViewState    = false;
								// 01/16/2006   We don't enable required fields until we attempt to save. 
								// This is to allow unrelated form actions; the Cancel button is a good example. 
								reqNAME.EnableClientScript = false;
								reqNAME.Enabled            = false;
								reqNAME.Style.Add("padding-left", "4px");
								tdField.Controls.Add(reqNAME);
							}
						}
						
						Image imgField = new Image();
						// 04/13/2006   Give the image a name so that it can be validated with SplendidTest. 
						imgField.ID = "img" + sDATA_FIELD;
						// 01/18/2010   Apply ACL Field Security. 
						imgField.Visible  = bLayoutMode || bIsReadable;
						try
						{
							if ( bLayoutMode )
							{
								Literal litField = new Literal();
								litField.Text = sDATA_FIELD;
								tdField.Controls.Add(litField);
							}
							else if ( rdr != null )
							{
								if ( !Sql.IsEmptyString(rdr[sDATA_FIELD]) )
								{
									ctlHidden.Value = Sql.ToString(rdr[sDATA_FIELD]);
									imgField.ImageUrl = "~/Images/Image.aspx?ID=" + ctlHidden.Value;
									// 04/13/2006   Only add the image if it exists. 
									tdField.Controls.Add(imgField);
									
									// 04/17/2006   Provide a clear button. 
									Literal litClear = new Literal();
									litClear.Text = "&nbsp; <input type=\"button\" class=\"button\" onclick=\"document.getElementById('" + ctlHidden.ClientID + "').value='';document.getElementById('" + imgField.ClientID + "').src='';" + "\"  value='" + "  " + L10n.Term(".LBL_CLEAR_BUTTON_LABEL" ) + "  " + "' title='" + L10n.Term(".LBL_CLEAR_BUTTON_TITLE" ) + "' />";
									tdField.Controls.Add(litClear);
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							Literal litField = new Literal();
							litField.Text = ex.Message;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "AddressButtons", true) == 0 && (btnCopyRight == null) && (btnCopyLeft == null) )
				{
					trField.Cells.Remove(tdField);
					tdLabel.Width = "10%";
					tdLabel.RowSpan = nROWSPAN;
					tdLabel.VAlign  = "middle";
					tdLabel.Align   = "center";
					tdLabel.Attributes.Remove("class");
					tdLabel.Attributes.Add("class", "tabFormAddDel");
					// 05/08/2010   Define the copy buttons outside the loop so that we can replace the javascriptwith embedded code.  
					// This is so that the javascript will run properly in the SixToolbar UpdatePanel. 
					btnCopyRight = new HtmlInputButton("button");
					btnCopyLeft  = new HtmlInputButton("button");
					Literal         litSpacer    = new Literal();
					tdLabel.Controls.Add(btnCopyRight);
					tdLabel.Controls.Add(litSpacer   );
					tdLabel.Controls.Add(btnCopyLeft );
					btnCopyRight.Attributes.Add("title"  , L10n.Term("Accounts.NTC_COPY_BILLING_ADDRESS" ));
					//btnCopyRight.Attributes.Add("onclick", "return copyAddressRight()");
					btnCopyRight.Value = ">>";
					litSpacer.Text = "<br><br>";
					btnCopyLeft .Attributes.Add("title"  , L10n.Term("Accounts.NTC_COPY_SHIPPING_ADDRESS" ));
					//btnCopyLeft .Attributes.Add("onclick", "return copyAddressLeft()");
					btnCopyLeft .Value = "<<";
					nColIndex = 0;
				}
				else if ( String.Compare(sFIELD_TYPE, "Hidden", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						HtmlInputHidden hidID = new HtmlInputHidden();
						tdField.Controls.Add(hidID);
						hidID.ID = sDATA_FIELD;
						try
						{
							if ( bLayoutMode )
							{
								TextBox txtNAME = new TextBox();
								tdField.Controls.Add(txtNAME);
								txtNAME.ReadOnly = true;
								// 11/25/2006    Turn off viewstate so that we can fix the text on postback. 
								txtNAME.EnableViewState = false;
								txtNAME.Text    = sDATA_FIELD;
								txtNAME.Enabled = false         ;
							}
							else
							{
								// 02/28/2008   When the hidden field is the first in the row, we end up with a blank row. 
								// Just ignore for now as IE does not have a problem with the blank row. 
								nCOLSPAN = -1;
								trLabel.Cells.Remove(tdLabel);
								tdField.Attributes.Add("style", "display:none");
								if ( !Sql.IsEmptyString(sDATA_FIELD) && rdr != null )
									hidID.Value = Sql.ToString(rdr[sDATA_FIELD]);
								// 11/25/2006   The team name should always default to the current user's private team. 
								// Make sure not to overwrite the value if this is a postback. 
								// The hidden field does not require the same viewstate fix as the txtNAME field. 
								else if ( sDATA_FIELD == "TEAM_ID" && rdr == null && !bIsPostBack )
									hidID.Value = Security.TEAM_ID.ToString();
								// 01/15/2007   Assigned To field will always default to the current user. 
								else if ( sDATA_FIELD == "ASSIGNED_USER_ID" && rdr == null && !bIsPostBack )
									hidID.Value = Security.USER_ID.ToString();
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
					}
				}
				// 08/24/2009   Add support for dynamic teams. 
				else if ( String.Compare(sFIELD_TYPE, "TeamSelect", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						TeamSelect ctlTeamSelect = tbl.Page.LoadControl("~/_controls/TeamSelect.ascx") as TeamSelect;
						tdField.Controls.Add(ctlTeamSelect);
						ctlTeamSelect.ID = sDATA_FIELD;
						// 05/06/2010   Use a special Page flag to override the default IsPostBack behavior. 
						ctlTeamSelect.NotPostBack = bNotPostBack;
						//ctlTeamSelect.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						ctlTeamSelect.Visible  = bLayoutMode || bIsReadable;
						ctlTeamSelect.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							Guid gTEAM_SET_ID = Guid.Empty;
							if ( rdr != null )
							{
								// 11/22/2010   Convert data reader to data table for Rules Wizard. 
								//vwSchema.RowFilter = "ColumnName = 'TEAM_SET_ID'";
								//if ( vwSchema.Count > 0 )
								if ( rdr.Table.Columns.Contains("TEAM_SET_ID") )
								{
									gTEAM_SET_ID = Sql.ToGuid(rdr["TEAM_SET_ID"]);
								}
							}
							// 08/31/2009  Don't provide defaults in a Search view or a Popup view. 
							bool bAllowDefaults = sEDIT_NAME.IndexOf(".Search") < 0 && sEDIT_NAME.IndexOf(".Popup") < 0;
							ctlTeamSelect.LoadLineItems(gTEAM_SET_ID, bAllowDefaults);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				// 10/21/2009   Add support for dynamic teams. 
				else if ( String.Compare(sFIELD_TYPE, "KBTagSelect", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						KBTagSelect ctlKBTagSelect = tbl.Page.LoadControl("~/_controls/KBTagSelect.ascx") as KBTagSelect;
						tdField.Controls.Add(ctlKBTagSelect);
						ctlKBTagSelect.ID = sDATA_FIELD;
						// 05/06/2010   Use a special Page flag to override the default IsPostBack behavior. 
						ctlKBTagSelect.NotPostBack = bNotPostBack;
						//ctlKBTagSelect.TabIndex = nFORMAT_TAB_INDEX;
						// 01/18/2010   Apply ACL Field Security. 
						ctlKBTagSelect.Visible  = bLayoutMode || bIsReadable;
						ctlKBTagSelect.Enabled  = bLayoutMode || bIsWriteable;
						try
						{
							Guid gID = Guid.Empty;
							if ( rdr != null )
							{
								gID = Sql.ToGuid(rdr["ID"]);
							}
							ctlKBTagSelect.LoadLineItems(gID);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				else
				{
					Literal litField = new Literal();
					tdField.Controls.Add(litField);
					litField.Text = "Unknown field type " + sFIELD_TYPE;
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "Unknown field type " + sFIELD_TYPE);
				}
				// 12/02/2007   Each view can now have its own number of data columns. 
				// This was needed so that search forms can have 4 data columns. The default is 2 columns. 
				if ( nCOLSPAN > 0 )
					nColIndex += nCOLSPAN;
				else if ( nCOLSPAN == 0 )
					nColIndex++;
				if ( nColIndex >= nDATA_COLUMNS )
					nColIndex = 0;
			}
			// 09/20/2012   We need a SCRIPT field that is form specific. 
			if ( dvFields.Count > 0 && !bLayoutMode )
			{
				try
				{
					string sEDIT_NAME   = Sql.ToString(dvFields[0]["EDIT_NAME"]);
					string sFORM_SCRIPT = Sql.ToString(dvFields[0]["SCRIPT"   ]);
					if ( !Sql.IsEmptyString(sFORM_SCRIPT) )
					{
						// 09/20/2012   The base ID is not the ID of the parent, but the ID of the TemplateControl. 
						sFORM_SCRIPT = sFORM_SCRIPT.Replace("SPLENDID_EDITVIEW_LAYOUT_ID", tbl.TemplateControl.ClientID);
						ScriptManager.RegisterStartupScript(tbl, typeof(System.String), sEDIT_NAME.Replace(".", "_") + "_SCRIPT", sFORM_SCRIPT, true);
					}
				}
				catch(Exception ex)
				{
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
				}
			}
			// 05/08/2010   Define the copy buttons outside the loop so that we can replace the javascript with embedded code.  
			// This is so that the javascript will run properly in the SixToolbar UpdatePanel. 
			if ( btnCopyRight != null && btnCopyLeft != null )
			{
				string[][] arrCopyFields = new string[14][];
				arrCopyFields[0] = new string[2] { "SHIPPING_ADDRESS_STREET"    , "BILLING_ADDRESS_STREET"    };
				arrCopyFields[1] = new string[2] { "SHIPPING_ADDRESS_CITY"      , "BILLING_ADDRESS_CITY"      };
				arrCopyFields[2] = new string[2] { "SHIPPING_ADDRESS_STATE"     , "BILLING_ADDRESS_STATE"     };
				arrCopyFields[3] = new string[2] { "SHIPPING_ADDRESS_POSTALCODE", "BILLING_ADDRESS_POSTALCODE"};
				arrCopyFields[4] = new string[2] { "SHIPPING_ADDRESS_COUNTRY"   , "BILLING_ADDRESS_COUNTRY"   };
				arrCopyFields[5] = new string[2] { "ALT_ADDRESS_STREET"         , "PRIMARY_ADDRESS_STREET"    };
				arrCopyFields[6] = new string[2] { "ALT_ADDRESS_CITY"           , "PRIMARY_ADDRESS_CITY"      };
				arrCopyFields[7] = new string[2] { "ALT_ADDRESS_STATE"          , "PRIMARY_ADDRESS_STATE"     };
				arrCopyFields[8] = new string[2] { "ALT_ADDRESS_POSTALCODE"     , "PRIMARY_ADDRESS_POSTALCODE"};
				arrCopyFields[9] = new string[2] { "ALT_ADDRESS_COUNTRY"        , "PRIMARY_ADDRESS_COUNTRY"   };
				// 08/21/2010   Also copy Account and Contact on Quotes, Orders and Invoices. 
				arrCopyFields[10] = new string[2] { "SHIPPING_ACCOUNT_NAME"      , "BILLING_ACCOUNT_NAME"      };
				arrCopyFields[11] = new string[2] { "SHIPPING_ACCOUNT_ID"        , "BILLING_ACCOUNT_ID"        };
				arrCopyFields[12] = new string[2] { "SHIPPING_CONTACT_NAME"      , "BILLING_CONTACT_NAME"      };
				arrCopyFields[13] = new string[2] { "SHIPPING_CONTACT_ID"        , "BILLING_CONTACT_ID"        };

				/*
				function copyAddressRight()
				{
					document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_STREET"    ).ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_STREET"    ).ClientID %>').value;
					document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_CITY"      ).ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_CITY"      ).ClientID %>').value;
					document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_STATE"     ).ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_STATE"     ).ClientID %>').value;
					document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_POSTALCODE").ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_POSTALCODE").ClientID %>').value;
					document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_COUNTRY"   ).ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_COUNTRY"   ).ClientID %>').value;
					return true;
				}
				function copyAddressLeft()
				{
					document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_STREET"    ).ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_STREET"    ).ClientID %>').value;
					document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_CITY"      ).ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_CITY"      ).ClientID %>').value;
					document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_STATE"     ).ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_STATE"     ).ClientID %>').value;
					document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_POSTALCODE").ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_POSTALCODE").ClientID %>').value;
					document.getElementById('<%= new DynamicControl(this, "BILLING_ADDRESS_COUNTRY"   ).ClientID %>').value = document.getElementById('<%= new DynamicControl(this, "SHIPPING_ADDRESS_COUNTRY"   ).ClientID %>').value;
					return true;
				}
				*/
				StringBuilder sbCopyRight = new StringBuilder();
				StringBuilder sbCopyLeft  = new StringBuilder();
				for ( int i = 0; i < arrCopyFields.Length; i++ )
				{
					Control ctl1 = tbl.FindControl(arrCopyFields[i][0]);
					Control ctl2 = tbl.FindControl(arrCopyFields[i][1]);
					if ( ctl1 != null && ctl2 != null )
					{
						// 02/01/2011   Cannot copy values from literal. 
						if ( !(ctl1 is Literal) && !(ctl2 is Literal) )
						{
							sbCopyRight.Append("document.getElementById('" + ctl1.ClientID + "').value = document.getElementById('" + ctl2.ClientID + "').value;");
							sbCopyLeft .Append("document.getElementById('" + ctl2.ClientID + "').value = document.getElementById('" + ctl1.ClientID + "').value;");
						}
					}
				}
				sbCopyRight.Append("return true;");
				sbCopyLeft .Append("return true;");

				btnCopyRight.Attributes.Add("onclick", sbCopyRight.ToString());
				btnCopyLeft .Attributes.Add("onclick", sbCopyLeft .ToString());
			}
		}
예제 #17
0
		// 04/11/2011   Add the layout flag so that we can provide a preview mode. 
		public static void AppendGridColumns(DataView dvFields, HtmlTable tbl, IDataReader rdr, L10N L10n, TimeZone T10n, CommandEventHandler Page_Command, bool bLayoutMode)
		{
			if ( tbl == null )
			{
				SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "HtmlTable is not defined");
				return;
			}
			// 01/07/2006   Show table borders in layout mode. This will help distinguish blank lines from wrapped lines. 
			if ( bLayoutMode )
				tbl.Border = 1;

			HtmlTableRow trAction = new HtmlTableRow();
			HtmlTableRow trHeader = new HtmlTableRow();
			HtmlTableRow trField  = new HtmlTableRow();
			tbl.Rows.Insert(0, trAction);
			tbl.Rows.Insert(1, trHeader);
			tbl.Rows.Insert(2, trField );
			trAction.Attributes.Add("class", "listViewThS1");
			trHeader.Attributes.Add("class", "listViewThS1");
			trField .Attributes.Add("class", "oddListRowS1");
			trAction.Visible = bLayoutMode;

			HttpSessionState Session = HttpContext.Current.Session;
			bool bSupportsDraggable = Sql.ToBoolean(Session["SupportsDraggable"]);
			foreach(DataRowView row in dvFields)
			{
				Guid   gID                         = Sql.ToGuid   (row["ID"                        ]);
				int    nCOLUMN_INDEX               = Sql.ToInteger(row["COLUMN_INDEX"              ]);
				string sCOLUMN_TYPE                = Sql.ToString (row["COLUMN_TYPE"               ]);
				string sHEADER_TEXT                = Sql.ToString (row["HEADER_TEXT"               ]);
				string sSORT_EXPRESSION            = Sql.ToString (row["SORT_EXPRESSION"           ]);
				string sITEMSTYLE_WIDTH            = Sql.ToString (row["ITEMSTYLE_WIDTH"           ]);
				string sITEMSTYLE_CSSCLASS         = Sql.ToString (row["ITEMSTYLE_CSSCLASS"        ]);
				string sITEMSTYLE_HORIZONTAL_ALIGN = Sql.ToString (row["ITEMSTYLE_HORIZONTAL_ALIGN"]);
				string sITEMSTYLE_VERTICAL_ALIGN   = Sql.ToString (row["ITEMSTYLE_VERTICAL_ALIGN"  ]);
				bool   bITEMSTYLE_WRAP             = Sql.ToBoolean(row["ITEMSTYLE_WRAP"            ]);
				string sDATA_FIELD                 = Sql.ToString (row["DATA_FIELD"                ]);
				string sDATA_FORMAT                = Sql.ToString (row["DATA_FORMAT"               ]);
				string sURL_FIELD                  = Sql.ToString (row["URL_FIELD"                 ]);
				string sURL_FORMAT                 = Sql.ToString (row["URL_FORMAT"                ]);
				string sURL_TARGET                 = Sql.ToString (row["URL_TARGET"                ]);
				string sLIST_NAME                  = Sql.ToString (row["LIST_NAME"                 ]);
				
				HtmlTableCell tdAction = new HtmlTableCell();
				trAction.Cells.Add(tdAction);
				tdAction.NoWrap = true;

				Literal litIndex = new Literal();
				tdAction.Controls.Add(litIndex);
				litIndex.Text = " " + nCOLUMN_INDEX.ToString() + " ";

				// 05/18/2013   Add drag handle. 
				if ( bSupportsDraggable )
				{
					Image imgDragIcon = new Image();
					imgDragIcon.SkinID = "draghandle_horz";
					imgDragIcon.Attributes.Add("draggable"  , "true");
					imgDragIcon.Attributes.Add("ondragstart", "event.dataTransfer.setData('Text', '" + nCOLUMN_INDEX.ToString() + "');");
					tdAction.Controls.Add(imgDragIcon);
					// 08/08/2013   IE does not support preventDefault. 
					// http://stackoverflow.com/questions/1000597/event-preventdefault-function-not-working-in-ie
					tdAction.Attributes.Add("ondragover", "LayoutDragOver(event, '" + nCOLUMN_INDEX.ToString() + "')");
					tdAction.Attributes.Add("ondrop"    , "LayoutDropIndex(event, '" + nCOLUMN_INDEX.ToString() + "')");
				}
				else
				{
					ImageButton btnMoveUp   = CreateLayoutImageButtonSkin(gID, "Layout.MoveUp"  , nCOLUMN_INDEX, L10n.Term(".LNK_LEFT"  ), "leftarrow_inline" , Page_Command);
					ImageButton btnMoveDown = CreateLayoutImageButtonSkin(gID, "Layout.MoveDown", nCOLUMN_INDEX, L10n.Term(".LNK_RIGHT" ), "rightarrow_inline", Page_Command);
					tdAction.Controls.Add(btnMoveUp  );
					tdAction.Controls.Add(btnMoveDown);
				}
				ImageButton btnInsert   = CreateLayoutImageButtonSkin(gID, "Layout.Insert"  , nCOLUMN_INDEX, L10n.Term(".LNK_INS"   ), "plus_inline"      , Page_Command);
				ImageButton btnEdit     = CreateLayoutImageButtonSkin(gID, "Layout.Edit"    , nCOLUMN_INDEX, L10n.Term(".LNK_EDIT"  ), "edit_inline"      , Page_Command);
				ImageButton btnDelete   = CreateLayoutImageButtonSkin(gID, "Layout.Delete"  , nCOLUMN_INDEX, L10n.Term(".LNK_DELETE"), "delete_inline"    , Page_Command);
				tdAction.Controls.Add(btnInsert  );
				tdAction.Controls.Add(btnEdit    );
				tdAction.Controls.Add(btnDelete  );
				
				HtmlTableCell tdHeader = new HtmlTableCell();
				trHeader.Cells.Add(tdHeader);
				tdHeader.NoWrap = true;
				
				HtmlTableCell tdField = new HtmlTableCell();
				trField.Cells.Add(tdField);
				tdField.NoWrap = true;

				Literal litHeader = new Literal();
				tdHeader.Controls.Add(litHeader);
				if ( bLayoutMode )
					litHeader.Text = sHEADER_TEXT;
				else
					litHeader.Text = L10n.Term(sHEADER_TEXT);

				Literal litField = new Literal();
				tdField.Controls.Add(litField);
				litField.Text = sDATA_FIELD;
				litField.Visible = bLayoutMode;
			}
		}
예제 #18
0
		// 08/07/2013   Add Undelete module. 
		public static DataTable AuditedModules()
		{
			System.Web.Caching.Cache Cache = HttpRuntime.Cache;
			L10N L10n = new L10N(HttpContext.Current.Session["USER_SETTINGS/CULTURE"] as string);
			DataTable dt = Cache.Get(L10n.NAME + ".vwMODULES_Audited") as DataTable;
			if ( dt == null )
			{
				try
				{
					DbProviderFactory dbf = DbProviderFactories.GetFactory();
					using ( IDbConnection con = dbf.CreateConnection() )
					{
						con.Open();
						string sSQL;
						sSQL = "select MODULE_NAME      " + ControlChars.CrLf
						     + "     , DISPLAY_NAME     " + ControlChars.CrLf
						     + "  from vwMODULES_Audited" + ControlChars.CrLf
						     + " order by MODULE_NAME   " + ControlChars.CrLf;
						using ( IDbCommand cmd = con.CreateCommand() )
						{
							cmd.CommandText = sSQL;
							using ( DbDataAdapter da = dbf.CreateDataAdapter() )
							{
								((IDbDataAdapter)da).SelectCommand = cmd;
								dt = new DataTable();
								da.Fill(dt);
								foreach(DataRow row in dt.Rows)
								{
									row["DISPLAY_NAME"] = L10n.Term(Sql.ToString(row["DISPLAY_NAME"]));
								}
								Cache.Insert(L10n.NAME + ".vwMODULES_Audited", dt, null, DefaultCacheExpiration(), Cache.NoSlidingExpiration);
							}
						}
					}
				}
				catch(Exception ex)
				{
					SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);
				}
			}
			return dt;
		}
예제 #19
0
		public static void AppendButtons(string sVIEW_NAME, Guid gASSIGNED_USER_ID, Control ctl, bool bIsMobile, DataRow rdr, L10N L10n, CommandEventHandler Page_Command)
		{
			if ( ctl == null )
			{
				SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "AppendButtons ctl is not defined");
				return;
			}
			//ctl.Controls.Clear();

			Hashtable hashIDs = new Hashtable();
			// 05/06/2010   Use a special Page flag to override the default IsPostBack behavior. 
			bool bIsPostBack = ctl.Page.IsPostBack;
			bool bNotPostBack = false;
			if ( ctl.TemplateControl is SplendidControl )
			{
				bNotPostBack = (ctl.TemplateControl as SplendidControl).NotPostBack;
				bIsPostBack = ctl.Page.IsPostBack && !bNotPostBack;
			}
			bool bShowUnassigned = Crm.Config.show_unassigned();
			DataTable dt = SplendidCache.DynamicButtons(sVIEW_NAME);
			if ( dt != null )
			{
				foreach(DataRow row in dt.Rows)
				{
					Guid   gID                 = Sql.ToGuid   (row["ID"                ]);
					int    nCONTROL_INDEX      = Sql.ToInteger(row["CONTROL_INDEX"     ]);
					string sCONTROL_TYPE       = Sql.ToString (row["CONTROL_TYPE"      ]);
					string sMODULE_NAME        = Sql.ToString (row["MODULE_NAME"       ]);
					string sMODULE_ACCESS_TYPE = Sql.ToString (row["MODULE_ACCESS_TYPE"]);
					string sTARGET_NAME        = Sql.ToString (row["TARGET_NAME"       ]);
					string sTARGET_ACCESS_TYPE = Sql.ToString (row["TARGET_ACCESS_TYPE"]);
					bool   bMOBILE_ONLY        = Sql.ToBoolean(row["MOBILE_ONLY"       ]);
					bool   bADMIN_ONLY         = Sql.ToBoolean(row["ADMIN_ONLY"        ]);
					string sCONTROL_TEXT       = Sql.ToString (row["CONTROL_TEXT"      ]);
					string sCONTROL_TOOLTIP    = Sql.ToString (row["CONTROL_TOOLTIP"   ]);
					string sCONTROL_ACCESSKEY  = Sql.ToString (row["CONTROL_ACCESSKEY" ]);
					string sCONTROL_CSSCLASS   = Sql.ToString (row["CONTROL_CSSCLASS"  ]);
					string sTEXT_FIELD         = Sql.ToString (row["TEXT_FIELD"        ]);
					string sARGUMENT_FIELD     = Sql.ToString (row["ARGUMENT_FIELD"    ]);
					string sCOMMAND_NAME       = Sql.ToString (row["COMMAND_NAME"      ]);
					string sURL_FORMAT         = Sql.ToString (row["URL_FORMAT"        ]);
					string sURL_TARGET         = Sql.ToString (row["URL_TARGET"        ]);
					string sONCLICK_SCRIPT     = Sql.ToString (row["ONCLICK_SCRIPT"    ]);
					// 07/28/2010   We need a flag to exclude a button from a mobile device. 
					bool   bEXCLUDE_MOBILE     = false;
					try
					{
						bEXCLUDE_MOBILE = Sql.ToBoolean(row["EXCLUDE_MOBILE"]);
					}
					catch
					{
					}
					// 03/14/2014   Allow hidden buttons to be created. 
					bool   bHIDDEN             = false;
					try
					{
						bHIDDEN = Sql.ToBoolean(row["HIDDEN"]);
					}
					catch
					{
					}

					// 09/01/2008   Give each button an ID to simplify validation. 
					// Attempt to name the control after the command name.  If no command name, then use the control text. 
					string sCONTROL_ID = String.Empty;
					if ( !Sql.IsEmptyString(sCOMMAND_NAME) )
					{
						sCONTROL_ID = sCOMMAND_NAME;
					}
					else if ( !Sql.IsEmptyString(sCONTROL_TEXT) )
					{
						sCONTROL_ID = sCONTROL_TEXT;
						if ( sCONTROL_TEXT.IndexOf('.') >= 0 )
						{
							sCONTROL_ID = sCONTROL_TEXT.Split('.')[1];
							sCONTROL_ID = sCONTROL_ID.Replace("LBL_", "");
							sCONTROL_ID = sCONTROL_ID.Replace("_BUTTON_LABEL", "");
						}
					}
					if ( !Sql.IsEmptyString(sCONTROL_ID) )
					{
						// 09/01/2008   Cleanup the ID. 
						sCONTROL_ID = sCONTROL_ID.Trim();
						sCONTROL_ID = sCONTROL_ID.Replace(' ', '_');
						sCONTROL_ID = sCONTROL_ID.Replace('.', '_');
						sCONTROL_ID = "btn" + sCONTROL_ID.ToUpper();
						// 12/16/2008   Add to hash after cleaning the ID. 
						if ( hashIDs.Contains(sCONTROL_ID) )
							sCONTROL_ID = sVIEW_NAME.Replace('.', '_') + "_" + nCONTROL_INDEX.ToString();
						if ( !hashIDs.Contains(sCONTROL_ID) )
							hashIDs.Add(sCONTROL_ID, null);
						else
							sCONTROL_ID = String.Empty;  // If ID still exists, then don't set the ID. 
					}

					// 03/21/2008   We need to use a view to search for the rows for the ColumnName. 
					// 11/22/2010   Convert data reader to data table for Rules Wizard. 
					//DataView vwSchema = null;
					//if ( rdr != null )
					//	vwSchema = new DataView(rdr.GetSchemaTable());

					string[] arrTEXT_FIELD = sTEXT_FIELD.Split(' ');
					object[] objTEXT_FIELD = new object[arrTEXT_FIELD.Length];
					for ( int i=0 ; i < arrTEXT_FIELD.Length; i++ )
					{
						if ( !Sql.IsEmptyString(arrTEXT_FIELD[i]) )
						{
							objTEXT_FIELD[i] = String.Empty;
							if ( rdr != null ) // && vwSchema != null
							{
								//vwSchema.RowFilter = "ColumnName = '" + Sql.EscapeSQL(arrTEXT_FIELD[i]) + "'";
								//if ( vwSchema.Count > 0 )
								// 11/22/2010   Convert data reader to data table for Rules Wizard. 
								if ( rdr.Table.Columns.Contains(arrTEXT_FIELD[i]) )
									objTEXT_FIELD[i] = Sql.ToString(rdr[arrTEXT_FIELD[i]]);
							}
						}
					}
					if ( String.Compare(sCONTROL_TYPE, "Button", true) == 0 )
					{
						Button btn = new Button();
						ctl.Controls.Add(btn);
						if ( !Sql.IsEmptyString(sCONTROL_ID) )
							btn.ID = sCONTROL_ID;
						if ( !Sql.IsEmptyString(sARGUMENT_FIELD) )
						{
							if ( rdr != null ) // && vwSchema != null )
							{
								//vwSchema.RowFilter = "ColumnName = '" + Sql.EscapeSQL(sARGUMENT_FIELD) + "'";
								//if ( vwSchema.Count > 0 )
								if ( rdr.Table.Columns.Contains(sARGUMENT_FIELD) )
									btn.CommandArgument = Sql.ToString(rdr[sARGUMENT_FIELD]);
							}
						}

						btn.Text            = "  " + L10n.Term(sCONTROL_TEXT) + "  ";
						btn.CssClass        = sCONTROL_CSSCLASS;
						btn.Command        += Page_Command;
						btn.CommandName     = sCOMMAND_NAME;
						btn.OnClientClick   = sONCLICK_SCRIPT;
						// 11/21/2008   On post back, we need to re-create the buttons, but don't change the visiblity flag. 
						// The problem is that we don't have the record at this early stage, so we cannot properly evaluate gASSIGNED_USER_ID. 
						// This is not an issue because .NET will restore the previous visibility state on post back. 
						if ( !bIsPostBack )
						{
							// 07/28/2010   We need a flag to exclude a button from a mobile device. 
							// 03/14/2014   Allow hidden buttons to be created. 
							btn.Visible         = (!bEXCLUDE_MOBILE || !bIsMobile) && (bMOBILE_ONLY && bIsMobile || !bMOBILE_ONLY) && (bADMIN_ONLY && Security.isAdmin || !bADMIN_ONLY) && !bHIDDEN;
							if ( btn.Visible && !Sql.IsEmptyString(sMODULE_NAME) && !Sql.IsEmptyString(sMODULE_ACCESS_TYPE) )
							{
								int nACLACCESS = Taoqi.Security.GetUserAccess(sMODULE_NAME, sMODULE_ACCESS_TYPE);
								// 08/11/2008 John.  Fix owner access rights. 
								// 10/27/2008 Brian.  Only show button if show_unassigned is enabled.
								// 11/21/2008   We need to make sure that an owner can create a new record. 
								btn.Visible = (nACLACCESS > ACL_ACCESS.OWNER) || (nACLACCESS == ACL_ACCESS.OWNER && ((Security.USER_ID == gASSIGNED_USER_ID) || (!bIsPostBack && rdr == null) || (rdr != null && bShowUnassigned && Sql.IsEmptyGuid(gASSIGNED_USER_ID))));
								if ( btn.Visible && !Sql.IsEmptyString(sTARGET_NAME) && !Sql.IsEmptyString(sTARGET_ACCESS_TYPE) )
								{
									// 08/11/2008 John.  Fix owner access rights.
									nACLACCESS = Taoqi.Security.GetUserAccess(sTARGET_NAME, sTARGET_ACCESS_TYPE);
									// 11/21/2008   We need to make sure that an owner can create a new record. 
									btn.Visible = (nACLACCESS > ACL_ACCESS.OWNER) || (nACLACCESS == ACL_ACCESS.OWNER && ((Security.USER_ID == gASSIGNED_USER_ID) || (!bIsPostBack && rdr == null) || (rdr != null && bShowUnassigned && Sql.IsEmptyGuid(gASSIGNED_USER_ID))));
								}
							}
						}
						if ( !Sql.IsEmptyString(sCONTROL_ACCESSKEY) )
						{
							btn.AccessKey = L10n.AccessKey(sCONTROL_ACCESSKEY);
						}
						if ( !Sql.IsEmptyString(sCONTROL_TOOLTIP) )
						{
							btn.ToolTip = L10n.Term (sCONTROL_TOOLTIP);
							if ( btn.ToolTip.Contains("[Alt]") )
							{
								if ( btn.AccessKey.Length > 0 )
									btn.ToolTip = btn.ToolTip.Replace("[Alt]", "[Alt+" + btn.AccessKey + "]");
								else
									btn.ToolTip = btn.ToolTip.Replace("[Alt]", String.Empty);
							}
						}
						btn.Attributes.Add("style", "margin-right: 3px;");
					}
					else if ( String.Compare(sCONTROL_TYPE, "HyperLink", true) == 0 )
					{
						HyperLink lnk = new HyperLink();
						ctl.Controls.Add(lnk);
						if ( !Sql.IsEmptyString(sCONTROL_ID) )
							lnk.ID          = sCONTROL_ID;
						lnk.Text        = L10n.Term(sCONTROL_TEXT);
						lnk.NavigateUrl = String.Format(sURL_FORMAT, objTEXT_FIELD);
						lnk.Target      = sURL_TARGET;
						lnk.CssClass    = sCONTROL_CSSCLASS;
						// 11/21/2008   On post back, we need to re-create the buttons, but don't change the visiblity flag. 
						// The problem is that we don't have the record at this early stage, so we cannot properly evaluate gASSIGNED_USER_ID. 
						// Not setting the visibility flag is not an issue because .NET will restore the previous visibility state on post back. 
						if ( !bIsPostBack )
						{
							// 07/28/2010   We need a flag to exclude a button from a mobile device. 
							// 03/14/2014   Allow hidden buttons to be created. 
							lnk.Visible     = (!bEXCLUDE_MOBILE || !bIsMobile) && (bMOBILE_ONLY && bIsMobile || !bMOBILE_ONLY) && (bADMIN_ONLY && Security.isAdmin || !bADMIN_ONLY) && !bHIDDEN;
							if ( lnk.Visible && !Sql.IsEmptyString(sMODULE_NAME) && !Sql.IsEmptyString(sMODULE_ACCESS_TYPE) )
							{
								int nACLACCESS = Taoqi.Security.GetUserAccess(sMODULE_NAME, sMODULE_ACCESS_TYPE);
								// 08/11/2008 John.  Fix owner access rights.
								// 10/27/2008 Brian.  Only show button if show_unassigned is enabled.
								// 11/21/2008   We need to make sure that an owner can create a new record. 
								lnk.Visible = (nACLACCESS > ACL_ACCESS.OWNER) || (nACLACCESS == ACL_ACCESS.OWNER && ((Security.USER_ID == gASSIGNED_USER_ID) || (!bIsPostBack && rdr == null) || (rdr != null && bShowUnassigned && Sql.IsEmptyGuid(gASSIGNED_USER_ID))));
								if ( lnk.Visible && !Sql.IsEmptyString(sTARGET_NAME) && !Sql.IsEmptyString(sTARGET_ACCESS_TYPE) )
								{
									// 08/11/2008 John.  Fix owner access rights.
									nACLACCESS = Taoqi.Security.GetUserAccess(sTARGET_NAME, sTARGET_ACCESS_TYPE);
									// 10/27/2008 Brian.  Only show button if show_unassigned is enabled.
									// 11/21/2008   We need to make sure that an owner can create a new record. 
									lnk.Visible = (nACLACCESS > ACL_ACCESS.OWNER) || (nACLACCESS == ACL_ACCESS.OWNER && ((Security.USER_ID == gASSIGNED_USER_ID) || (!bIsPostBack && rdr == null) || (rdr != null && bShowUnassigned && Sql.IsEmptyGuid(gASSIGNED_USER_ID))));
								}
							}
						}
						if ( !Sql.IsEmptyString(sONCLICK_SCRIPT) )
						{
							lnk.Attributes.Add("onclick", sONCLICK_SCRIPT);
						}
						if ( !Sql.IsEmptyString(sCONTROL_ACCESSKEY) )
						{
							lnk.AccessKey = L10n.AccessKey(sCONTROL_ACCESSKEY);
						}
						if ( !Sql.IsEmptyString(sCONTROL_TOOLTIP) )
						{
							lnk.ToolTip = L10n.Term(sCONTROL_TOOLTIP);
							if ( lnk.ToolTip.Contains("[Alt]") )
							{
								if ( lnk.AccessKey.Length > 0 )
									lnk.ToolTip = lnk.ToolTip.Replace("[Alt]", "[Alt+" + lnk.AccessKey + "]");
								else
									lnk.ToolTip = lnk.ToolTip.Replace("[Alt]", String.Empty);
							}
						}
						// 04/04/2008   Links need additional spacing.
						lnk.Attributes.Add("style", "margin-right: 3px; margin-left: 3px;");
					}
					else if ( String.Compare(sCONTROL_TYPE, "ButtonLink", true) == 0 )
					{
						Button btn = new Button();
						ctl.Controls.Add(btn);
						if ( !Sql.IsEmptyString(sCONTROL_ID) )
							btn.ID              = sCONTROL_ID;
						btn.Text            = "  " + L10n.Term(sCONTROL_TEXT) + "  ";
						btn.CssClass        = sCONTROL_CSSCLASS;
						// 03/21/2008   Keep the command just in case we are in a browser that does not support javascript. 
						btn.Command        += Page_Command;
						btn.CommandName     = sCOMMAND_NAME;
						// 08/22/2010   Provide a way to override the default URL behavior and run javascript. 
						if ( !Sql.IsEmptyString(sONCLICK_SCRIPT) )
							btn.OnClientClick   = String.Format(sONCLICK_SCRIPT, objTEXT_FIELD);
						else
							btn.OnClientClick   = "window.location.href='" + Sql.EscapeJavaScript(String.Format(sURL_FORMAT, objTEXT_FIELD)) + "'; return false;";
						// 11/21/2008   On post back, we need to re-create the buttons, but don't change the visiblity flag. 
						// The problem is that we don't have the record at this early stage, so we cannot properly evaluate gASSIGNED_USER_ID. 
						// Not setting the visibility flag is not an issue because .NET will restore the previous visibility state on post back. 
						if ( !bIsPostBack )
						{
							// 07/28/2010   We need a flag to exclude a button from a mobile device. 
							// 03/14/2014   Allow hidden buttons to be created. 
							btn.Visible     = (!bEXCLUDE_MOBILE || !bIsMobile) && (bMOBILE_ONLY && bIsMobile || !bMOBILE_ONLY) && (bADMIN_ONLY && Security.isAdmin || !bADMIN_ONLY) && !bHIDDEN;
							if ( btn.Visible && !Sql.IsEmptyString(sMODULE_NAME) && !Sql.IsEmptyString(sMODULE_ACCESS_TYPE) )
							{
								int nACLACCESS = Taoqi.Security.GetUserAccess(sMODULE_NAME, sMODULE_ACCESS_TYPE);
								// 08/11/2008 John.  Fix owner access rights.
								// 10/27/2008 Brian.  Only show button if show_unassigned is enabled.
								// 11/21/2008   We need to make sure that an owner can create a new record. 
								btn.Visible = (nACLACCESS > ACL_ACCESS.OWNER) || (nACLACCESS == ACL_ACCESS.OWNER && ((Security.USER_ID == gASSIGNED_USER_ID) || (!bIsPostBack && rdr == null) || (rdr != null && bShowUnassigned && Sql.IsEmptyGuid(gASSIGNED_USER_ID))));
								if ( btn.Visible && !Sql.IsEmptyString(sTARGET_NAME) && !Sql.IsEmptyString(sTARGET_ACCESS_TYPE) )
								{
									// 08/11/2008 John.  Fix owner access rights.
									nACLACCESS = Taoqi.Security.GetUserAccess(sTARGET_NAME, sTARGET_ACCESS_TYPE);
									// 10/27/2008 Brian.  Only show button if show_unassigned is enabled.
									// 11/21/2008   We need to make sure that an owner can create a new record. 
									btn.Visible = (nACLACCESS > ACL_ACCESS.OWNER) || (nACLACCESS == ACL_ACCESS.OWNER && ((Security.USER_ID == gASSIGNED_USER_ID) || (!bIsPostBack && rdr == null) || (rdr != null && bShowUnassigned && Sql.IsEmptyGuid(gASSIGNED_USER_ID))));
								}
							}
						}
						if ( !Sql.IsEmptyString(sCONTROL_ACCESSKEY) )
						{
							btn.AccessKey = L10n.AccessKey(sCONTROL_ACCESSKEY);
						}
						if ( !Sql.IsEmptyString(sCONTROL_TOOLTIP) )
						{
							btn.ToolTip = L10n.Term (sCONTROL_TOOLTIP);
							if ( btn.ToolTip.Contains("[Alt]") )
							{
								if ( btn.AccessKey.Length > 0 )
									btn.ToolTip = btn.ToolTip.Replace("[Alt]", "[Alt+" + btn.AccessKey + "]");
								else
									btn.ToolTip = btn.ToolTip.Replace("[Alt]", String.Empty);
							}
						}
						btn.Attributes.Add("style", "margin-right: 3px;");
					}
				}
			}
		}
예제 #20
0
		public static DataTable List(string sListName)
		{
			System.Web.Caching.Cache Cache = HttpRuntime.Cache;

			L10N L10n = new L10N(HttpContext.Current.Session["USER_SETTINGS/CULTURE"] as string);
            DataTable dt = Cache.Get(L10n.NAME + "." + sListName) as DataTable;
			if ( dt == null )
			{
				try
				{
					DbProviderFactory dbf = DbProviderFactories.GetFactory();
					using ( IDbConnection con = dbf.CreateConnection() )
					{
						con.Open();
						string sSQL;
						// 10/13/2005   Use distinct because the same list appears to be duplicated in various modules. 
						// appointment_filter_dom is in an Activities and a History module.
						// ORDER BY items must appear in the select list if SELECT DISTINCT is specified. 
						sSQL = "select distinct              " + ControlChars.CrLf
						     + "       NAME                  " + ControlChars.CrLf
						     + "     , DISPLAY_NAME          " + ControlChars.CrLf
						     + "     , LIST_ORDER            " + ControlChars.CrLf
						     + "  from vwTERMINOLOGY         " + ControlChars.CrLf
						     + " where lower(LIST_NAME) = @LIST_NAME" + ControlChars.CrLf  // 03/06/2006   Oracle is case sensitive, and we modify the case of L10n.NAME to be lower. 
						     + "   and lower(LANG     ) = @LANG     " + ControlChars.CrLf  // 03/06/2006   Oracle is case sensitive, and we modify the case of L10n.NAME to be lower. 
						     + " order by LIST_ORDER         " + ControlChars.CrLf;
						using ( IDbCommand cmd = con.CreateCommand() )
						{
							cmd.CommandText = sSQL;
							// 03/06/2006   Oracle is case sensitive, and we modify the case of L10n.NAME to be lower. 
							Sql.AddParameter(cmd, "@LIST_NAME", sListName.ToLower());
							Sql.AddParameter(cmd, "@LANG"     , L10n.NAME.ToLower());
							
							using ( DbDataAdapter da = dbf.CreateDataAdapter() )
							{
								((IDbDataAdapter)da).SelectCommand = cmd;
								dt = new DataTable();
								da.Fill(dt);
								Cache.Insert(L10n.NAME + "." + sListName, dt, null, DefaultCacheExpiration(), Cache.NoSlidingExpiration);
							}
						}
						// 12/03/2005   Most lists require data, so if the language-specific list does not exist, just use English. 
						if ( dt.Rows.Count == 0 )
						{
							if ( String.Compare(L10n.NAME, "en-US", true) != 0 )
							{
								using ( IDbCommand cmd = con.CreateCommand() )
								{
									cmd.CommandText = sSQL;
									// 03/06/2006   Oracle is case sensitive, and we modify the case of L10n.NAME to be lower. 
									Sql.AddParameter(cmd, "@LIST_NAME", sListName.ToLower());
									Sql.AddParameter(cmd, "@LANG"     , "en-US"  .ToLower());
							
									using ( DbDataAdapter da = dbf.CreateDataAdapter() )
									{
										((IDbDataAdapter)da).SelectCommand = cmd;
										dt = new DataTable();
										da.Fill(dt);
										Cache.Insert(L10n.NAME + "." + sListName, dt, null, DefaultCacheExpiration(), Cache.NoSlidingExpiration);
									}
								}
							}
						}
					}
				}
				catch(Exception ex)
				{
					SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);
					// 10/16/2005   Ignore list errors. 
					// 03/30/2006   IBM DB2 is returning an error, which is causing a data-binding error. 
					// SQL1585N A system temporary table space with sufficient page size does not exist. 
					// 03/30/2006   In case of error, we should return NULL. 
					return null;
				}
			}
			return dt;
		}
예제 #21
0
		public static void AppendDetailViewFields(DataView dvFields, HtmlTable tbl, DataRow rdr, L10N L10n, TimeZone T10n, CommandEventHandler Page_Command, bool bLayoutMode)
		{
			bool bIsMobile = false;
			SplendidPage Page = tbl.Page as SplendidPage;
			if ( Page != null )
				bIsMobile = Page.IsMobile;
			// 11/23/2009   We need to make sure that AJAX is available before we use it. 
			ScriptManager mgrAjax = ScriptManager.GetCurrent(tbl.Page);

			HtmlTableRow tr = null;
			// 11/28/2005   Start row index using the existing count so that headers can be specified. 
			int nRowIndex = tbl.Rows.Count - 1;
			int nColIndex = 0;
			// 01/07/2006   Show table borders in layout mode. This will help distinguish blank lines from wrapped lines. 
			if ( bLayoutMode )
				tbl.Border = 1;
			// 03/30/2007   Convert the currency values before displaying. 
			// The UI culture should already be set to format the currency. 
			Currency C10n = HttpContext.Current.Items["C10n"] as Currency;
			HttpSessionState Session = HttpContext.Current.Session;
			// 11/15/2007   If there are no fields in the detail view, then hide the entire table. 
			// This allows us to hide the table by removing all detail view fields. 
			// 09/12/2009   There is no reason to hide the table when in layout mode. 
			if ( dvFields.Count == 0 && tbl.Rows.Count <= 1 && !bLayoutMode )
				tbl.Visible = false;
			
			// 01/27/2008   We need the schema table to determine if the data label is free-form text. 
			// 03/21/2008   We need to use a view to search for the rows for the ColumnName. 
			// 01/18/2010   To apply ACL Field Security, we need to know if the current record has an ASSIGNED_USER_ID field, and its value. 
			Guid gASSIGNED_USER_ID = Guid.Empty;
			//DataView vwSchema = null;
			if ( rdr != null )
			{
				// 11/22/2010   Convert data reader to data table for Rules Wizard. 
				//vwSchema = new DataView(rdr.GetSchemaTable());
				//vwSchema.RowFilter = "ColumnName = 'ASSIGNED_USER_ID'";
				//if ( vwSchema.Count > 0 )
				if ( rdr.Table.Columns.Contains("ASSIGNED_USER_ID") )
				{
					gASSIGNED_USER_ID = Sql.ToGuid(rdr["ASSIGNED_USER_ID"]);
				}
			}

			// 08/02/2010   The cell fields need to be outside the loop in order to support COLSPAN=-1. 
			HtmlTableCell tdLabel = null;
			HtmlTableCell tdField = null;
			// 01/01/2008   Pull config flag outside the loop. 
			bool bEnableTeamManagement = Crm.Config.enable_team_management();
			// 08/28/2009   Allow dynamic teams to be turned off. 
			bool bEnableDynamicTeams   = Crm.Config.enable_dynamic_teams();
			HttpApplicationState Application = HttpContext.Current.Application;
			// 08/22/2012   We need to prevent duplicate names. 
			Hashtable hashLABEL_IDs = new Hashtable();
			bool bSupportsDraggable = Sql.ToBoolean(Session["SupportsDraggable"]);
			// 12/13/2013   Allow each line item to have a separate tax rate. 
			bool bEnableTaxLineItems = Sql.ToBoolean(HttpContext.Current.Application["CONFIG.Orders.TaxLineItems"]);
			foreach(DataRowView row in dvFields)
			{
				string sDETAIL_NAME = Sql.ToString (row["DETAIL_NAME"]);
				Guid   gID          = Sql.ToGuid   (row["ID"         ]);
				int    nFIELD_INDEX = Sql.ToInteger(row["FIELD_INDEX"]);
				string sFIELD_TYPE  = Sql.ToString (row["FIELD_TYPE" ]);
				string sDATA_LABEL  = Sql.ToString (row["DATA_LABEL" ]);
				string sDATA_FIELD  = Sql.ToString (row["DATA_FIELD" ]);
				string sDATA_FORMAT = Sql.ToString (row["DATA_FORMAT"]);
				string sLIST_NAME   = Sql.ToString (row["LIST_NAME"  ]);
				int    nCOLSPAN     = Sql.ToInteger(row["COLSPAN"    ]);
				string sLABEL_WIDTH = Sql.ToString (row["LABEL_WIDTH"]);
				string sFIELD_WIDTH = Sql.ToString (row["FIELD_WIDTH"]);
				int    nDATA_COLUMNS= Sql.ToInteger(row["DATA_COLUMNS"]);
				// 08/02/2010   Move URL fields to the top of the loop. 
				string sURL_FIELD   = Sql.ToString (row["URL_FIELD"  ]);
				string sURL_FORMAT  = Sql.ToString (row["URL_FORMAT" ]);
				string sURL_TARGET  = Sql.ToString (row["URL_TARGET" ]);
				// 06/12/2009   Add TOOL_TIP for help hover.
				string sTOOL_TIP    = String.Empty;
				try
				{
					sTOOL_TIP = Sql.ToString (row["TOOL_TIP"]);
				}
				catch(Exception ex)
				{
					// 06/12/2009   The TOOL_TIP is not in the view, then log the error and continue. 
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
				}
				// 02/16/2010   Add MODULE_TYPE so that we can lookup custom field IDs. 
				string sMODULE_TYPE = String.Empty;
				try
				{
					sMODULE_TYPE = Sql.ToString (row["MODULE_TYPE"]);
				}
				catch(Exception ex)
				{
					// 06/16/2010   The MODULE_TYPE is not in the view, then log the error and continue. 
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
				}
				// 10/09/2010   Add PARENT_FIELD so that we can establish dependent listboxes. 
				string sPARENT_FIELD = String.Empty;
				try
				{
					sPARENT_FIELD = Sql.ToString (row["PARENT_FIELD"]);
				}
				catch(Exception ex)
				{
					// 10/09/2010   The PARENT_FIELD is not in the view, then log the error and continue. 
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
				}
				// 12/02/2007   Each view can now have its own number of data columns. 
				// This was needed so that search forms can have 4 data columns. The default is 2 columns. 
				if ( nDATA_COLUMNS == 0 )
					nDATA_COLUMNS = 2;

				// 01/18/2010   To apply ACL Field Security, we need to know if the Module Name, which we will extract from the EditView Name. 
				string sMODULE_NAME = String.Empty;
				string[] arrDETAIL_NAME = sDETAIL_NAME.Split('.');
				if ( arrDETAIL_NAME.Length > 0 )
					sMODULE_NAME = arrDETAIL_NAME[0];
				bool bIsReadable  = true;
				// 06/16/2010   sDATA_FIELD may be empty. 
				if ( SplendidInit.bEnableACLFieldSecurity && !Sql.IsEmptyString(sDATA_FIELD) )
				{
					Security.ACL_FIELD_ACCESS acl = Security.GetUserFieldSecurity(sMODULE_NAME, sDATA_FIELD, gASSIGNED_USER_ID);
					bIsReadable  = acl.IsReadable();
				}

				// 11/25/2006   If Team Management has been disabled, then convert the field to a blank. 
				// Keep the field, but treat it as blank so that field indexes will still be valid. 
				// 12/03/2006   Allow the team field to be visible during layout. 
				// 12/03/2006   The correct field is TEAM_NAME.  We don't use TEAM_ID in the detail view. 
				// 08/24/2009   Add support for dynamic teams. 
				if ( !bLayoutMode && (sDATA_FIELD == "TEAM_NAME" || sDATA_FIELD == "TEAM_SET_NAME") )
				{
					if ( !bEnableTeamManagement )
					{
						sFIELD_TYPE = "Blank";
					}
					else if ( bEnableDynamicTeams )
					{
						// 08/28/2009   If dynamic teams are enabled, then always use the set name. 
						sDATA_LABEL = ".LBL_TEAM_SET_NAME";
						sDATA_FIELD = "TEAM_SET_NAME";
					}
				}
				// 12/13/2013   Allow each product to have a default tax rate. 
				if ( !bLayoutMode && sDATA_FIELD == "TAX_CLASS" )
				{
					if ( bEnableTaxLineItems )
					{
						// 08/28/2009   If dynamic teams are enabled, then always use the set name. 
						sDATA_LABEL = "ProductTemplates.LBL_TAXRATE_ID";
						sDATA_FIELD = "TAXRATE_ID";
						sLIST_NAME  = "TaxRates";
					}
				}

				// 04/04/2010   Hide the Exchange Folder field if disabled for this module or user. 
				if ( !bLayoutMode && sDATA_FIELD == "EXCHANGE_FOLDER" )
				{
					if ( !Crm.Modules.ExchangeFolders(sMODULE_NAME) || !Security.HasExchangeAlias() )
					{
						sFIELD_TYPE = "Blank";
					}
				}
				// 09/02/2012   A separator will create a new table. We need to match the outer and inner layout. 
				if ( String.Compare(sFIELD_TYPE, "Separator", true) == 0 )
				{
					System.Web.UI.HtmlControls.HtmlTable tblNew = new System.Web.UI.HtmlControls.HtmlTable();
					tblNew.Attributes.Add("class", "tabDetailView");
					tblNew.Style.Add(HtmlTextWriterStyle.MarginTop, "5px");
					// 09/27/2012   Separator can have an ID and can have a style so that it can be hidden. 
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
						tblNew.ID = sDATA_FIELD;
					if ( !Sql.IsEmptyString(sDATA_FORMAT) && !bLayoutMode )
						tblNew.Style.Add(HtmlTextWriterStyle.Display, sDATA_FORMAT);
					int nParentIndex = tbl.Parent.Controls.IndexOf(tbl);
					tbl.Parent.Controls.AddAt(nParentIndex + 1, tblNew);
					tbl = tblNew;
					
					nRowIndex = -1;
					nColIndex = 0;
					tdLabel = null;
					tdField = null;
					if ( bLayoutMode )
						tbl.Border = 1;
					else
						continue;
				}
				// 11/17/2007   On a mobile device, each new field is on a new row. 
				// 08/02/2010  COLSPAN == -1 means that a new column should not be created. 
				if ( (nCOLSPAN >= 0 && nColIndex == 0) || tr == null || bIsMobile )
				{
					// 11/25/2005   Don't pre-create a row as we don't want a blank
					// row at the bottom.  Add rows just before they are needed. 
					nRowIndex++;
					tr = new HtmlTableRow();
					tbl.Rows.Insert(nRowIndex, tr);
				}
				if ( bLayoutMode )
				{
					HtmlTableCell tdAction = new HtmlTableCell();
					tr.Cells.Add(tdAction);
					tdAction.Attributes.Add("class", "tabDetailViewDL");
					tdAction.NoWrap = true;

					Literal litIndex = new Literal();
					litIndex.Text = "&nbsp;" + nFIELD_INDEX.ToString() + "&nbsp;";
					tdAction.Controls.Add(litIndex   );

					// 05/26/2007   Fix the terms. The are in the Dropdown module. 
					// 05/18/2013   Add drag handle. 
					if ( bSupportsDraggable )
					{
						Image imgDragIcon = new Image();
						imgDragIcon.SkinID = "draghandle_table";
						imgDragIcon.Attributes.Add("draggable"  , "true");
						imgDragIcon.Attributes.Add("ondragstart", "event.dataTransfer.setData('Text', '" + nFIELD_INDEX.ToString() + "');");
						tdAction.Controls.Add(imgDragIcon);
						// 08/08/2013   IE does not support preventDefault. 
						// http://stackoverflow.com/questions/1000597/event-preventdefault-function-not-working-in-ie
						tdAction.Attributes.Add("ondragover", "LayoutDragOver(event, '" + nFIELD_INDEX.ToString() + "')");
						tdAction.Attributes.Add("ondrop"    , "LayoutDropIndex(event, '" + nFIELD_INDEX.ToString() + "')");
					}
					else
					{
						ImageButton btnMoveUp   = CreateLayoutImageButtonSkin(gID, "Layout.MoveUp"  , nFIELD_INDEX, L10n.Term("Dropdown.LNK_UP"    ), "uparrow_inline"  , Page_Command);
						ImageButton btnMoveDown = CreateLayoutImageButtonSkin(gID, "Layout.MoveDown", nFIELD_INDEX, L10n.Term("Dropdown.LNK_DOWN"  ), "downarrow_inline", Page_Command);
						tdAction.Controls.Add(btnMoveUp  );
						tdAction.Controls.Add(btnMoveDown);
					}
					ImageButton btnInsert   = CreateLayoutImageButtonSkin(gID, "Layout.Insert"  , nFIELD_INDEX, L10n.Term("Dropdown.LNK_INS"   ), "plus_inline"     , Page_Command);
					ImageButton btnEdit     = CreateLayoutImageButtonSkin(gID, "Layout.Edit"    , nFIELD_INDEX, L10n.Term("Dropdown.LNK_EDIT"  ), "edit_inline"     , Page_Command);
					ImageButton btnDelete   = CreateLayoutImageButtonSkin(gID, "Layout.Delete"  , nFIELD_INDEX, L10n.Term("Dropdown.LNK_DELETE"), "delete_inline"   , Page_Command);
					tdAction.Controls.Add(btnInsert  );
					tdAction.Controls.Add(btnEdit    );
					tdAction.Controls.Add(btnDelete  );
				}
				// 08/02/2010   Move literal label up so that it can be accessed when processing a blank. 
				Literal   litLabel = new Literal();
				// 08/22/2012   Try and create a safe label ID so that it can be accessed using FindControl(). 
				// We are using the DATA_FIELD to match the logic in the EditView area. 
				if ( !Sql.IsEmptyString(sDATA_FIELD) && !hashLABEL_IDs.Contains(sDATA_FIELD) )
				{
					litLabel.ID = sDATA_FIELD.Replace(" ", "_").Replace(".", "_") + "_LABEL";
					hashLABEL_IDs.Add(sDATA_FIELD, null);
				}
				HyperLink lnkField = null;
				if ( nCOLSPAN >= 0 || tdLabel == null || tdField == null )
				{
					tdLabel = new HtmlTableCell();
					tdField = new HtmlTableCell();
					tdLabel.Attributes.Add("class", "tabDetailViewDL");
					tdLabel.VAlign = "top";
					tdLabel.Width  = sLABEL_WIDTH;
					tdField.Attributes.Add("class", "tabDetailViewDF");
					tdField.VAlign = "top";
					tr.Cells.Add(tdLabel);
					tr.Cells.Add(tdField);
					if ( nCOLSPAN > 0 )
					{
						tdField.ColSpan = nCOLSPAN;
						if ( bLayoutMode )
							tdField.ColSpan++;
					}
					// 11/28/2005   Don't use the field width if COLSPAN is specified as we want it to take the rest of the table.  The label width will be sufficient. 
					if ( nCOLSPAN == 0 )
						tdField.Width  = sFIELD_WIDTH;
					
					// 08/02/2010   The label will get skipped if we are processing COLSPAN=-1. 
					tdLabel.Controls.Add(litLabel);
					// 01/18/2010   Apply ACL Field Security. 
					litLabel.Visible = bLayoutMode || bIsReadable;
					//litLabel.Text = nFIELD_INDEX.ToString() + " (" + nRowIndex.ToString() + "," + nColIndex.ToString() + ")";
					try
					{
						if ( bLayoutMode )
							litLabel.Text = sDATA_LABEL;
						else if ( sDATA_LABEL.IndexOf(".") >= 0 )
							litLabel.Text = L10n.Term(sDATA_LABEL);
						else if ( !Sql.IsEmptyString(sDATA_LABEL) && rdr != null )
						{
							// 01/27/2008   If the data label is not in the schema table, then it must be free-form text. 
							// It is not used often, but we allow the label to come from the result set.  For example,
							// when the parent is stored in the record, we need to pull the module name from the record. 
							litLabel.Text = sDATA_LABEL;
							// 11/22/2010   Convert data reader to data table for Rules Wizard. 
							//if ( vwSchema != null )
							if ( rdr != null )
							{
								//vwSchema.RowFilter = "ColumnName = '" + Sql.EscapeSQL(sDATA_LABEL) + "'";
								//if ( vwSchema.Count > 0 )
								if ( rdr.Table.Columns.Contains(sDATA_LABEL) )
									litLabel.Text = Sql.ToString(rdr[sDATA_LABEL]) + L10n.Term("Calls.LBL_COLON");
							}
						}
						// 07/15/2006   Always put something for the label so that table borders will look right. 
						else
							litLabel.Text = "&nbsp;";

						// 06/12/2009   Add Tool Tip hover. 
						// 11/23/2009   Only add tool tip if AJAX is available and this is not a mobile device. 
						// 01/18/2010   Only add tool tip if the label is visible. 
						if ( !bIsMobile && mgrAjax != null && !Sql.IsEmptyString(sTOOL_TIP) && !Sql.IsEmptyString(sDATA_FIELD) && litLabel.Visible )
						{
							Image imgToolTip = new Image();
							imgToolTip.SkinID = "tooltip_inline";
							imgToolTip.ID     = sDATA_FIELD + "_TOOLTIP_IMAGE";
							tdLabel.Controls.Add(imgToolTip);
							
							Panel pnlToolTip = new Panel();
							pnlToolTip.ID       = sDATA_FIELD + "_TOOLTIP_PANEL";
							pnlToolTip.CssClass = "tooltip";
							tdLabel.Controls.Add(pnlToolTip);

							Literal litToolTip = new Literal();
							litToolTip.Text = sDATA_FIELD;
							pnlToolTip.Controls.Add(litToolTip);
							if ( bLayoutMode )
								litToolTip.Text = sTOOL_TIP;
							else if ( sTOOL_TIP.IndexOf(".") >= 0 )
								litToolTip.Text = L10n.Term(sTOOL_TIP);
							else
								litToolTip.Text = sTOOL_TIP;
							
							AjaxControlToolkit.HoverMenuExtender hovToolTip = new AjaxControlToolkit.HoverMenuExtender();
							hovToolTip.TargetControlID = imgToolTip.ID;
							hovToolTip.PopupControlID  = pnlToolTip.ID;
							hovToolTip.PopupPosition   = AjaxControlToolkit.HoverMenuPopupPosition.Right;
							hovToolTip.PopDelay        = 50;
							hovToolTip.OffsetX         = 0;
							hovToolTip.OffsetY         = 0;
							tdLabel.Controls.Add(hovToolTip);
						}
					}
					catch(Exception ex)
					{
						SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						litLabel.Text = ex.Message;
					}
				}
				
				if ( String.Compare(sFIELD_TYPE, "Blank", true) == 0 )
				{
					Literal litField = new Literal();
					tdField.Controls.Add(litField);
					if ( bLayoutMode )
					{
						litLabel.Text = "*** BLANK ***";
						litField.Text = "*** BLANK ***";
					}
					else
					{
						// 12/03/2006   Make sure to clear the label.  This is necessary to convert a TEAM to blank when disabled. 
						litLabel.Text = "&nbsp;";
						litField.Text = "&nbsp;";
					}
				}
				// 09/03/2012   A separator does nothing in Layout mode. 
				else if ( String.Compare(sFIELD_TYPE, "Separator", true) == 0 )
				{
					if ( bLayoutMode )
					{
						litLabel.Text = "*** SEPARATOR ***";
						nColIndex = nDATA_COLUMNS;
						tdField.ColSpan = 2 * nDATA_COLUMNS - 1;
						// 09/03/2012   When in layout mode, we need to add a column for arrangement. 
						tdField.ColSpan++;
					}
				}
				// 09/03/2012   A header is similar to a label, but without the data field. 
				else if ( String.Compare(sFIELD_TYPE, "Header", true) == 0 )
				{
					Literal litField = new Literal();
					tdField.Controls.Add(litField);
					litField.Text = "&nbsp;";
					if ( !bLayoutMode )
					{
						litLabel.Text = "<h4>" + litLabel.Text + "</h4>";
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "Line", true) == 0 )
				{
					if ( bLayoutMode )
					{
						Literal litField = new Literal();
						tdField.Controls.Add(litField);
						litLabel.Text = "*** LINE ***";
						litField.Text = "*** LINE ***";
					}
					else
					{
						tr.Cells.Clear();
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "String", true) == 0 )
				{
					if ( bLayoutMode )
					{
						Literal litField = new Literal();
						litField.Text = sDATA_FIELD;
						tdField.Controls.Add(litField);
					}
					else if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/06/2005   Wrap all string fields in a SPAN tag to simplify regression testing. 
						HtmlGenericControl spnField = new HtmlGenericControl("span");
						tdField.Controls.Add(spnField);
						spnField.ID = sDATA_FIELD;

						Literal litField = new Literal();
						spnField.Controls.Add(litField);
						// 01/18/2010   Apply ACL Field Security. 
						litField.Visible = bLayoutMode || bIsReadable;
						try
						{
							string[] arrLIST_NAME  = sLIST_NAME .Split(' ');
							string[] arrDATA_FIELD = sDATA_FIELD.Split(' ');
							// 10/09/2010   Add PARENT_FIELD so that we can establish dependent listboxes. 
							string[] arrPARENT_FIELD = sPARENT_FIELD.Split(' ');
							object[] objDATA_FIELD = new object[arrDATA_FIELD.Length];
							for ( int i=0 ; i < arrDATA_FIELD.Length; i++ )
							{
								if ( arrDATA_FIELD[i].IndexOf(".") >= 0 )
								{
									objDATA_FIELD[i] = L10n.Term(arrDATA_FIELD[i]);
								}
								// 10/09/2010   Add PARENT_FIELD so that we can establish dependent listboxes. 
								else if ( !Sql.IsEmptyString(sPARENT_FIELD) && !Sql.IsEmptyString(sLIST_NAME) )
								{
									if ( arrPARENT_FIELD.Length == arrLIST_NAME.Length && arrLIST_NAME.Length == arrDATA_FIELD.Length )
									{
										if ( rdr != null )
										{
											string sPARENT_LIST_NAME = Sql.ToString(rdr[arrPARENT_FIELD[i]]);
											if ( !Sql.IsEmptyString(sPARENT_LIST_NAME) )
											{
												bool bCustomCache = false;
												objDATA_FIELD[i] = SplendidCache.CustomList(sPARENT_LIST_NAME, Sql.ToString(rdr[arrDATA_FIELD[i]]), ref bCustomCache);
												if ( bCustomCache )
													continue;
												if ( Sql.ToString(rdr[arrDATA_FIELD[i]]).StartsWith("<?xml") )
												{
													StringBuilder sb = new StringBuilder();
													XmlDocument xml = new XmlDocument();
													xml.LoadXml(Sql.ToString(rdr[arrDATA_FIELD[i]]));
													XmlNodeList nlValues = xml.DocumentElement.SelectNodes("Value");
													foreach ( XmlNode xValue in nlValues )
													{
														if ( sb.Length > 0 )
															sb.Append(", ");
														sb.Append(L10n.Term("." + sPARENT_LIST_NAME + ".", xValue.InnerText));
													}
													objDATA_FIELD[i] = sb.ToString();
												}
												else
												{
													objDATA_FIELD[i] = L10n.Term("." + sPARENT_LIST_NAME + ".", rdr[arrDATA_FIELD[i]]);
												}
											}
											else
												objDATA_FIELD[i] = String.Empty;
										}
										else
											objDATA_FIELD[i] = String.Empty;
									}
								}
								else if ( !Sql.IsEmptyString(sLIST_NAME) )
								{
									if ( arrLIST_NAME.Length == arrDATA_FIELD.Length )
									{
										if ( rdr != null )
										{
											// 08/06/2008   Use an array to define the custom caches so that list is in the Cache module. 
											// This should reduce the number of times that we have to edit the SplendidDynamic module. 
											bool bCustomCache = false;
											// 08/10/2008   Use a shared function to simplify access to Custom Cache.
											objDATA_FIELD[i] = SplendidCache.CustomList(arrLIST_NAME[i], Sql.ToString(rdr[arrDATA_FIELD[i]]), ref bCustomCache);
											if ( bCustomCache )
												continue;
											// 02/12/2008   If the list contains XML, then treat as a multi-selection. 
											if ( Sql.ToString(rdr[arrDATA_FIELD[i]]).StartsWith("<?xml") )
											{
												StringBuilder sb = new StringBuilder();
												XmlDocument xml = new XmlDocument();
												xml.LoadXml(Sql.ToString(rdr[arrDATA_FIELD[i]]));
												XmlNodeList nlValues = xml.DocumentElement.SelectNodes("Value");
												foreach ( XmlNode xValue in nlValues )
												{
													if ( sb.Length > 0 )
														sb.Append(", ");
													sb.Append(L10n.Term("." + arrLIST_NAME[i] + ".", xValue.InnerText));
												}
												objDATA_FIELD[i] = sb.ToString();
											}
											else
											{
												objDATA_FIELD[i] = L10n.Term("." + arrLIST_NAME[i] + ".", rdr[arrDATA_FIELD[i]]);
											}
										}
										else
											objDATA_FIELD[i] = String.Empty;
									}
								}
								else if ( !Sql.IsEmptyString(arrDATA_FIELD[i]) )
								{
									if ( rdr != null && rdr[arrDATA_FIELD[i]] != DBNull.Value)
									{
										// 12/05/2005   If the data is a DateTime field, then make sure to perform the timezone conversion. 
										if ( rdr[arrDATA_FIELD[i]].GetType() == Type.GetType("System.DateTime") )
											objDATA_FIELD[i] = T10n.FromServerTime(rdr[arrDATA_FIELD[i]]);
										// 02/16/2010   Add MODULE_TYPE so that we can lookup custom field IDs. 
										// 02/16/2010   Move ToGuid to the function so that it can be captured if invalid. 
										else if ( !Sql.IsEmptyString(sMODULE_TYPE) )
											objDATA_FIELD[i] = Crm.Modules.ItemName(Application, sMODULE_TYPE, rdr[arrDATA_FIELD[i]]);
										else
											objDATA_FIELD[i] = rdr[arrDATA_FIELD[i]];
									}
									else
										objDATA_FIELD[i] = String.Empty;
								}
							}
							if ( rdr != null )
							{
								// 01/09/2006   Allow DATA_FORMAT to be optional.   If missing, write data directly. 
								if ( sDATA_FORMAT == String.Empty )
								{
									for ( int i=0; i < arrDATA_FIELD.Length; i++ )
										arrDATA_FIELD[i] = Sql.ToString(objDATA_FIELD[i]);
									litField.Text = String.Join(" ", arrDATA_FIELD);
								}
								else if ( sDATA_FORMAT == "{0:c}" && C10n != null )
								{
									// 03/30/2007   Convert DetailView currencies on the fly. 
									// 05/05/2007   In an earlier step, we convert NULLs to empty strings. 
									// Attempts to convert to decimal will generate an error: Input string was not in a correct format.
									if ( !(objDATA_FIELD[0] is string) )
									{
										Decimal d = C10n.ToCurrency(Convert.ToDecimal(objDATA_FIELD[0]));
										litField.Text = d.ToString("c");
									}
								}
								else
									litField.Text = String.Format(sDATA_FORMAT, objDATA_FIELD);
								/*
								// 08/02/2010   Add javascript to the output. 
								// 08/02/2010   The javascript will be moved to a separate record. 
								if ( !Sql.IsEmptyString(sURL_FIELD) && !Sql.IsEmptyString(sURL_FORMAT) )
								{
									Literal litUrlField = new Literal();
									tdField.Controls.Add(litUrlField);
									string[] arrURL_FIELD = sURL_FIELD.Split(' ');
									object[] objURL_FIELD = new object[arrURL_FIELD.Length];
									for ( int i=0 ; i < arrURL_FIELD.Length; i++ )
									{
										if ( !Sql.IsEmptyString(arrURL_FIELD[i]) )
										{
											// 07/26/2007   Make sure to escape the javascript string. 
											if ( row[arrURL_FIELD[i]] != DBNull.Value )
												objURL_FIELD[i] = Sql.EscapeJavaScript(Sql.ToString(rdr[arrURL_FIELD[i]]));
											else
												objURL_FIELD[i] = String.Empty;
										}
									}
									// 12/03/2009   LinkedIn Company Profile requires a span tag to insert the link.
									litUrlField.Text = "&nbsp;<span id=\"" + String.Format(sURL_TARGET, objURL_FIELD) + "\"></span>";
									litUrlField.Text += "<script type=\"text/javascript\"> " + String.Format(sURL_FORMAT, objURL_FIELD) + "</script>";
								}
								*/
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							litField.Text = ex.Message;
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "CheckBox", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						CheckBox chkField = new CheckBox();
						tdField.Controls.Add(chkField);
						chkField.Enabled  = false     ;
						chkField.CssClass = "checkbox";
						// 03/16/2006   Give the checkbox a name so that it can be validated with SplendidTest. 
						chkField.ID       = sDATA_FIELD;
						// 01/18/2010   Apply ACL Field Security. 
						chkField.Visible  = bLayoutMode || bIsReadable;
						try
						{
							if ( rdr != null )
								chkField.Checked = Sql.ToBoolean(rdr[sDATA_FIELD]);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						}
						if ( bLayoutMode )
						{
							Literal litField = new Literal();
							litField.Text = sDATA_FIELD;
							tdField.Controls.Add(litField);
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "Button", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						Button btnField = new Button();
						tdField.Controls.Add(btnField);
						btnField.CssClass = "button";
						// 03/16/2006   Give the button a name so that it can be validated with SplendidTest. 
						btnField.ID       = sDATA_FIELD;
						// 01/18/2010   Apply ACL Field Security. 
						btnField.Visible  = bLayoutMode || bIsReadable;
						if ( Page_Command != null )
						{
							btnField.Command    += Page_Command;
							btnField.CommandName = sDATA_FORMAT  ;
						}
						try
						{
							if ( bLayoutMode )
							{
								btnField.Text    = sDATA_FIELD;
								btnField.Enabled = false      ;
							}
							else if ( sDATA_FIELD.IndexOf(".") >= 0 )
							{
								btnField.Text = L10n.Term(sDATA_FIELD);
							}
							else if ( !Sql.IsEmptyString(sDATA_FIELD) && rdr != null )
							{
								btnField.Text = Sql.ToString(rdr[sDATA_FIELD]);
							}
							btnField.Attributes.Add("title", btnField.Text);
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							btnField.Text = ex.Message;
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "Textbox", true) == 0 )
				{
					/*
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						TextBox txtField = new TextBox();
						tdField.Controls.Add(txtField);
						txtField.ReadOnly = true;
						txtField.TextMode = TextBoxMode.MultiLine;
						// 03/16/2006   Give the textbox a name so that it can be validated with SplendidTest. 
						txtField.ID       = sDATA_FIELD;
						try
						{
							string[] arrDATA_FORMAT = sDATA_FORMAT.Split(',');
							if ( arrDATA_FORMAT.Length == 2 )
							{
								txtField.Rows    = Sql.ToInteger(arrDATA_FORMAT[0]);
								txtField.Columns = Sql.ToInteger(arrDATA_FORMAT[1]);
							}
							if ( bLayoutMode )
							{
								txtField.Text = sDATA_FIELD;
							}
							else if ( !Sql.IsEmptyString(sDATA_FIELD) && rdr != null )
							{
								txtField.Text = Sql.ToString(rdr[sDATA_FIELD]);
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							txtField.Text = ex.Message;
						}
					}
					*/
					// 07/07/2007   Instead of using a real textbox, just replace new lines with <br />. 
					// This will perserve a majority of the HTML formating if it exists. 
					if ( bLayoutMode )
					{
						Literal litField = new Literal();
						litField.Text = sDATA_FIELD;
						tdField.Controls.Add(litField);
					}
					else if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						// 12/06/2005   Wrap all string fields in a SPAN tag to simplify regression testing. 
						HtmlGenericControl spnField = new HtmlGenericControl("span");
						tdField.Controls.Add(spnField);
						spnField.ID = sDATA_FIELD;

						Literal litField = new Literal();
						spnField.Controls.Add(litField);
						// 01/18/2010   Apply ACL Field Security. 
						litField.Visible = bLayoutMode || bIsReadable;
						try
						{
							if ( rdr != null )
							{
								string sDATA = Sql.ToString(rdr[sDATA_FIELD]);
								// 07/07/2007   Emails may not have the proper \r\n terminators, so perform a few extra steps to ensure clean data. 
								// 06/04/2010   Try and prevent excess blank lines. 
								//sDATA = EmailUtils.NormalizeDescription(sDATA);
								litField.Text = sDATA;
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							litField.Text = ex.Message;
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "HyperLink", true) == 0 || String.Compare(sFIELD_TYPE, "ModuleLink", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) && (!Sql.IsEmptyString(sURL_FIELD) || String.Compare(sFIELD_TYPE, "ModuleLink", true) == 0) )
					{
						lnkField = new HyperLink();
						tdField.Controls.Add(lnkField);
						lnkField.Target   = sURL_TARGET;
						lnkField.CssClass = "tabDetailViewDFLink";
						// 03/16/2006   Give the hyperlink a name so that it can be validated with SplendidTest. 
						lnkField.ID       = sDATA_FIELD;
						// 01/18/2010   Apply ACL Field Security. 
						lnkField.Visible = bLayoutMode || bIsReadable;
						try
						{
							if ( bLayoutMode )
							{
								lnkField.Text    = sDATA_FIELD;
								lnkField.Enabled = false      ;
							}
							else if ( rdr != null )
							{
								if ( !Sql.IsEmptyString(rdr[sDATA_FIELD]) )
								{
									// 01/09/2006   Allow DATA_FORMAT to be optional.   If missing, write data directly. 
									if ( Sql.IsEmptyString(sDATA_FORMAT) )
									{
										// 02/16/2010   Add MODULE_TYPE so that we can lookup custom field IDs. 
										// 02/16/2010   Move ToGuid to the function so that it can be captured if invalid. 
										if ( !Sql.IsEmptyString(sMODULE_TYPE) )
											lnkField.Text = Crm.Modules.ItemName(Application, sMODULE_TYPE, rdr[sDATA_FIELD]);
										else
											lnkField.Text = Sql.ToString(rdr[sDATA_FIELD]);
									}
									else
									{
										// 02/16/2010   Add MODULE_TYPE so that we can lookup custom field IDs. 
										// 02/16/2010   Move ToGuid to the function so that it can be captured if invalid. 
										if ( !Sql.IsEmptyString(sMODULE_TYPE) )
											lnkField.Text = String.Format(sDATA_FORMAT, Crm.Modules.ItemName(Application, sMODULE_TYPE, rdr[sDATA_FIELD]));
										else
											lnkField.Text = String.Format(sDATA_FORMAT, Sql.ToString(rdr[sDATA_FIELD]));
									}
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							lnkField.Text = ex.Message;
						}
						try
						{
							if ( bLayoutMode )
							{
								lnkField.NavigateUrl = sURL_FIELD;
							}
							else if ( rdr != null )
							{
								// 03/19/2013   URL_FIELD should support multiple fields. 
								string[] arrURL_FIELD = sURL_FIELD.Split(' ');
								object[] objURL_FIELD = new object[arrURL_FIELD.Length];
								for ( int i=0 ; i < arrURL_FIELD.Length; i++ )
								{
									if ( !Sql.IsEmptyString(arrURL_FIELD[i]) )
									{
										if ( rdr != null && rdr[arrURL_FIELD[i]] != DBNull.Value )
										{
											if ( rdr[arrURL_FIELD[i]].GetType() == Type.GetType("System.DateTime") )
												objURL_FIELD[i] = HttpUtility.UrlEncode(Sql.ToString(T10n.FromServerTime(rdr[arrURL_FIELD[i]])));
											else
											{
												// 04/08/2013   Web site URLs should not be UrlEncoded as it will not be clickable. 
												string sURL_VALUE = Sql.ToString(rdr[arrURL_FIELD[i]]);
												if ( sURL_VALUE.Contains("://") )
													objURL_FIELD[i] = sURL_VALUE;
												else
													objURL_FIELD[i] = HttpUtility.UrlEncode(sURL_VALUE);
											}
										}
										else
											objURL_FIELD[i] = String.Empty;
									}
								}
								// 09/04/2010   sURL_FIELD will be empty when used with a custom field. 
								if ( !Sql.IsEmptyString(sURL_FIELD) )
								{
									// 01/09/2006   Allow DATA_FORMAT to be optional.   If missing, write data directly. 
									// 06/08/2012   Check sURL_FORMAT instead of DATA_FORMAT. 
									if ( Sql.IsEmptyString(sURL_FORMAT) )
										lnkField.NavigateUrl = Sql.ToString(objURL_FIELD[0]);
									else
										lnkField.NavigateUrl = String.Format(sURL_FORMAT, objURL_FIELD);
								}
								// 02/16/2010   Add MODULE_TYPE so that we can lookup custom field IDs. 
								else if ( !Sql.IsEmptyString(sMODULE_TYPE) )
								{
									// 09/04/2010   This should be a URL_FORMAT test. 
									if ( Sql.IsEmptyString(sURL_FORMAT) )
									{
										// 02/18/2010   Get the Module Relative Path so that Project and Project Task will be properly handled. 
										// In these cases, the type is singular and the path is plural. 
										string sRELATIVE_PATH = Sql.ToString(Application["Modules." + sMODULE_TYPE + ".RelativePath"]);
										if ( Sql.IsEmptyString(sRELATIVE_PATH) )
											sRELATIVE_PATH = "~/" + sMODULE_TYPE + "/";
										lnkField.NavigateUrl = sRELATIVE_PATH + "view.aspx?ID=" + Sql.ToString(objURL_FIELD[0]);
									}
									else
									{
										lnkField.NavigateUrl = String.Format(sURL_FORMAT, objURL_FIELD);
									}
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							lnkField.NavigateUrl = ex.Message;
						}
					}
				}
				// 11/23/2010   Provide a link to the file. 
				else if ( String.Compare(sFIELD_TYPE, "File", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						lnkField = new HyperLink();
						lnkField.ID = sDATA_FIELD;
						lnkField.Visible = bLayoutMode || bIsReadable;
						try
						{
							if ( bLayoutMode )
							{
								Literal litField = new Literal();
								litField.Text = sDATA_FIELD;
								tdField.Controls.Add(litField);
							}
							else if ( rdr != null )
							{
								if ( !Sql.IsEmptyString(rdr[sDATA_FIELD]) )
								{
									lnkField.NavigateUrl = "~/Images/Image.aspx?ID=" + Sql.ToString(rdr[sDATA_FIELD]);
									lnkField.Text = Crm.Modules.ItemName(Application, "Images", rdr[sDATA_FIELD]);
									tdField.Controls.Add(lnkField);
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							lnkField.Text = ex.Message;
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "Image", true) == 0 )
				{
					if ( !Sql.IsEmptyString(sDATA_FIELD) )
					{
						Image imgField = new Image();
						// 04/13/2006   Give the image a name so that it can be validated with SplendidTest. 
						imgField.ID = sDATA_FIELD;
						// 01/18/2010   Apply ACL Field Security. 
						imgField.Visible = bLayoutMode || bIsReadable;
						try
						{
							if ( bLayoutMode )
							{
								Literal litField = new Literal();
								litField.Text = sDATA_FIELD;
								tdField.Controls.Add(litField);
							}
							else if ( rdr != null )
							{
								if ( !Sql.IsEmptyString(rdr[sDATA_FIELD]) )
								{
									imgField.ImageUrl = "~/Images/Image.aspx?ID=" + Sql.ToString(rdr[sDATA_FIELD]);
									// 04/13/2006   Only add the image if it exists. 
									tdField.Controls.Add(imgField);
								}
							}
						}
						catch(Exception ex)
						{
							SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
							lnkField.Text = ex.Message;
						}
					}
				}
				else if ( String.Compare(sFIELD_TYPE, "IFrame", true) == 0 )
				{
					Literal litField = new Literal();
					litField.Visible = bLayoutMode || bIsReadable;
					tdField.Controls.Add(litField);
					try
					{
						string sIFRAME_SRC    = String.Empty;
						// 08/02/2010   The iFrame height is stored in the URL Target field. 
						string sIFRAME_HEIGHT = sURL_TARGET;
						if ( Sql.IsEmptyString(sIFRAME_HEIGHT) )
							sIFRAME_HEIGHT = "200";
						if ( !Sql.IsEmptyString(sURL_FIELD) )
						{
							if ( bLayoutMode )
							{
								litField.Text = sURL_FIELD;
							}
							else if ( rdr != null )
							{
								string[] arrURL_FIELD = sURL_FIELD.Split(' ');
								object[] objURL_FIELD = new object[arrURL_FIELD.Length];
								for ( int i=0 ; i < arrURL_FIELD.Length; i++ )
								{
									if ( !Sql.IsEmptyString(arrURL_FIELD[i]) )
									{
										if ( rdr != null && rdr[arrURL_FIELD[i]] != DBNull.Value)
										{
											if ( rdr[arrURL_FIELD[i]].GetType() == Type.GetType("System.DateTime") )
												objURL_FIELD[i] = HttpUtility.UrlEncode(Sql.ToString(T10n.FromServerTime(rdr[arrURL_FIELD[i]])));
											else
												objURL_FIELD[i] = HttpUtility.UrlEncode(Sql.ToString(rdr[arrURL_FIELD[i]]));
										}
										else
											objURL_FIELD[i] = String.Empty;
									}
								}
								sIFRAME_SRC = String.Format(sURL_FORMAT, objURL_FIELD);
							}
						}
						else if ( !Sql.IsEmptyString(sDATA_FIELD) )
						{
							if ( bLayoutMode )
							{
								litField.Text = sDATA_FIELD;
							}
							else if ( rdr != null )
							{
								sIFRAME_SRC = Sql.ToString(rdr[sDATA_FIELD]);
							}
						}
						if ( !Sql.IsEmptyString(sIFRAME_SRC) )
							litField.Text = "<iframe src=\"" + sIFRAME_SRC + "\" height=\"" + sIFRAME_HEIGHT + "\" width=\"100%\"/></iframe>";
					}
					catch(Exception ex)
					{
						SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						litField.Text = ex.Message;
					}
				}
				// 08/02/2010   Create a seprate JavaScript field type. 
				else if ( String.Compare(sFIELD_TYPE, "JavaScript", true) == 0 )
				{
					Literal litField = new Literal();
					litField.Visible = bLayoutMode || bIsReadable;
					tdField.Controls.Add(litField);
					try
					{
						if ( bLayoutMode )
						{
							litField.Text = sURL_FIELD;
						}
						else if ( !Sql.IsEmptyString(sURL_FIELD) && !Sql.IsEmptyString(sURL_FORMAT) )
						{
							string[] arrURL_FIELD = sURL_FIELD.Split(' ');
							object[] objURL_FIELD = new object[arrURL_FIELD.Length];
							for ( int i=0 ; i < arrURL_FIELD.Length; i++ )
							{
								if ( !Sql.IsEmptyString(arrURL_FIELD[i]) )
								{
									// 07/26/2007   Make sure to escape the javascript string. 
									if ( rdr[arrURL_FIELD[i]] != DBNull.Value )
										objURL_FIELD[i] = Sql.EscapeJavaScript(Sql.ToString(rdr[arrURL_FIELD[i]]));
									else
										objURL_FIELD[i] = String.Empty;
								}
							}
							// 12/03/2009   LinkedIn Company Profile requires a span tag to insert the link.
							litField.Text = "&nbsp;<span id=\"" + String.Format(sURL_TARGET, objURL_FIELD) + "\"></span>";
							litField.Text += "<script type=\"text/javascript\"> " + String.Format(sURL_FORMAT, objURL_FIELD) + "</script>";
						}
					}
					catch(Exception ex)
					{
						SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
						litField.Text = ex.Message;
					}
				}
				else
				{
					Literal litField = new Literal();
					tdField.Controls.Add(litField);
					litField.Text = "Unknown field type " + sFIELD_TYPE;
					// 01/07/2006   Don't report the error in layout mode. 
					if ( !bLayoutMode )
						SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "Unknown field type " + sFIELD_TYPE);
				}
				// 12/02/2007   Each view can now have its own number of data columns. 
				// This was needed so that search forms can have 4 data columns. The default is 2 columns. 
				if ( nCOLSPAN > 0 )
					nColIndex += nCOLSPAN;
				else if ( nCOLSPAN == 0 )
					nColIndex++;
				if ( nColIndex >= nDATA_COLUMNS )
					nColIndex = 0;
			}
			// 09/20/2012   We need a SCRIPT field that is form specific. 
			if ( dvFields.Count > 0 && !bLayoutMode )
			{
				try
				{
					string sDETAIL_NAME = Sql.ToString(dvFields[0]["DETAIL_NAME"]);
					string sFORM_SCRIPT = Sql.ToString(dvFields[0]["SCRIPT"     ]);
					if ( !Sql.IsEmptyString(sFORM_SCRIPT) )
					{
						// 09/20/2012   The base ID is not the ID of the parent, but the ID of the TemplateControl. 
						sFORM_SCRIPT = sFORM_SCRIPT.Replace("SPLENDID_DETAILVIEW_LAYOUT_ID", tbl.TemplateControl.ClientID);
						ScriptManager.RegisterStartupScript(tbl, typeof(System.String), sDETAIL_NAME.Replace(".", "_") + "_SCRIPT", sFORM_SCRIPT, true);
					}
				}
				catch(Exception ex)
				{
					SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), ex);
				}
			}
		}
예제 #22
0
		public static DataTable WorkflowRelationships()
		{
			System.Web.Caching.Cache Cache = HttpRuntime.Cache;
			// 08/06/2008   Module names are returned translated, so make sure to cache based on the language. 
			L10N L10n = new L10N(HttpContext.Current.Session["USER_SETTINGS/CULTURE"] as string);
			DataTable dt = Cache.Get(L10n.NAME + ".vwRELATIONSHIPS_Workflow") as DataTable;
			if ( dt == null )
			{
				try
				{
					DbProviderFactory dbf = DbProviderFactories.GetFactory();
					using ( IDbConnection con = dbf.CreateConnection() )
					{
						con.Open();
						string sSQL;
						sSQL = "select *                        " + ControlChars.CrLf
						     + "  from vwRELATIONSHIPS_Workflow" + ControlChars.CrLf;
						using ( IDbCommand cmd = con.CreateCommand() )
						{
							cmd.CommandText = sSQL;
							using ( DbDataAdapter da = dbf.CreateDataAdapter() )
							{
								((IDbDataAdapter)da).SelectCommand = cmd;
								dt = new DataTable();
								da.Fill(dt);
								foreach(DataRow row in dt.Rows)
								{
									row["DISPLAY_NAME"] = L10n.Term(Sql.ToString(row["DISPLAY_NAME"]));
								}
								Cache.Insert(L10n.NAME + ".vwRELATIONSHIPS_Workflow", dt, null, DefaultCacheExpiration(), Cache.NoSlidingExpiration);
							}
						}
					}
				}
				catch(Exception ex)
				{
					SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);
				}
			}
			return dt;
		}
예제 #23
0
파일: RulesUtil.cs 프로젝트: huamouse/Taoqi
		public SplendidControlThis(SplendidControl Container, string sModule, DataTable Table)
		{
			this.Container = Container;
			this.Module    = sModule  ;
			this.Table     = Table    ;
			this.L10n      = Container.GetL10n();
		}
예제 #24
0
		public static DataTable ImportModules()
		{
			System.Web.Caching.Cache Cache = HttpRuntime.Cache;
			// 08/06/2008   Module names are returned translated, so make sure to cache based on the language. 
			L10N L10n = new L10N(HttpContext.Current.Session["USER_SETTINGS/CULTURE"] as string);
			DataTable dt = Cache.Get(L10n.NAME + ".vwMODULES_Import_" + Security.USER_ID.ToString()) as DataTable;
			if ( dt == null )
			{
				try
				{
					DbProviderFactory dbf = DbProviderFactories.GetFactory();
					using ( IDbConnection con = dbf.CreateConnection() )
					{
						con.Open();
						string sSQL;
						sSQL = "select MODULE_NAME             " + ControlChars.CrLf
						     + "     , DISPLAY_NAME            " + ControlChars.CrLf
						     + "  from vwMODULES_Import        " + ControlChars.CrLf
						     + " where USER_ID = @USER_ID      " + ControlChars.CrLf
						     + "    or USER_ID is null         " + ControlChars.CrLf;
						using ( IDbCommand cmd = con.CreateCommand() )
						{
							cmd.CommandText = sSQL;
							Sql.AddParameter(cmd, "@USER_ID", Security.USER_ID);
							using ( DbDataAdapter da = dbf.CreateDataAdapter() )
							{
								((IDbDataAdapter)da).SelectCommand = cmd;
								dt = new DataTable();
								da.Fill(dt);
								foreach(DataRow row in dt.Rows)
								{
									row["DISPLAY_NAME"] = L10n.Term(Sql.ToString(row["DISPLAY_NAME"]));
								}
								Cache.Insert(L10n.NAME + ".vwMODULES_Import_" + Security.USER_ID.ToString(), dt, null, DefaultCacheExpiration(), Cache.NoSlidingExpiration);
							}
						}
					}
				}
				catch(Exception ex)
				{
					SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);
					// 10/16/2005  Ignore list errors. 
				}
			}
			return dt;
		}
예제 #25
0
파일: RulesUtil.cs 프로젝트: huamouse/Taoqi
		public SplendidImportThis(L10N L10n, string sModule, DataRow Row, IDbCommand cmdImport, IDbCommand cmdImportCSTM)
		{
			this.L10n              = L10n         ;
			this.Row               = Row          ;
			this.Import            = cmdImport    ;
			this.ImportCSTM        = cmdImportCSTM;
			this.Module            = sModule      ;
			this.gASSIGNED_USER_ID = Guid.Empty   ;
			
			IDbDataParameter par = Sql.FindParameter(cmdImport, "ASSIGNED_USER_ID");
			if ( par != null )
				gASSIGNED_USER_ID = Sql.ToGuid(par.Value);
		}
예제 #26
0
		public static void AppendEditViewFields(string sEDIT_NAME, HtmlTable tbl, DataRow rdr, L10N L10n, TimeZone T10n)
		{
			if ( tbl == null )
			{
				SplendidError.SystemWarning(new StackTrace(true).GetFrame(0), "HtmlTable is not defined for " + sEDIT_NAME);
				return;
			}
			DataTable dtFields = SplendidCache.EditViewFields(sEDIT_NAME);
			AppendEditViewFields(dtFields.DefaultView, tbl, rdr, L10n, T10n, null, false, String.Empty);
		}
예제 #27
0
파일: RulesUtil.cs 프로젝트: huamouse/Taoqi
		public SplendidReportThis(HttpApplicationState Application, L10N L10n, string sModule, DataTable Table)
		{
			this.Application       = Application;
			this.L10n              = L10n       ;
			this.Module            = sModule    ;
			this.Table             = Table      ;
			this.gASSIGNED_USER_ID = Guid.Empty ;
		}
예제 #28
0
		// 12/04/2010   Add support for Business Rules Framework to Reports. 
		public static void ApplyReportRules(L10N L10n, Guid gPRE_LOAD_EVENT_ID, Guid gPOST_LOAD_EVENT_ID, DataTable dt)
		{
			if ( !Sql.IsEmptyGuid(gPRE_LOAD_EVENT_ID) )
			{
				DataTable dtFields = SplendidCache.ReportRules(gPRE_LOAD_EVENT_ID);
				if ( dtFields.Rows.Count > 0 )
				{
					string sMODULE_NAME = Sql.ToString(dtFields.Rows[0]["MODULE_NAME"]);
					string sXOML        = Sql.ToString(dtFields.Rows[0]["XOML"       ]);
					if ( !Sql.IsEmptyString(sXOML) )
					{
						RuleSet rules = RulesUtil.Deserialize(sXOML);
						RuleValidation validation = new RuleValidation(typeof(SplendidReportThis), null);
						// 11/11/2010   Validate so that we can get more information on a runtime error. 
						rules.Validate(validation);
						if ( validation.Errors.HasErrors )
						{
							throw(new Exception(RulesUtil.GetValidationErrors(validation)));
						}
						SplendidReportThis swThis = new SplendidReportThis(HttpContext.Current.Application, L10n, sMODULE_NAME, dt);
						RuleExecution exec = new RuleExecution(validation, swThis);
						rules.Execute(exec);
					}
				}
			}
			if ( !Sql.IsEmptyGuid(gPOST_LOAD_EVENT_ID) )
			{
				DataTable dtFields = SplendidCache.ReportRules(gPOST_LOAD_EVENT_ID);
				if ( dtFields.Rows.Count > 0 )
				{
					string sMODULE_NAME = Sql.ToString(dtFields.Rows[0]["MODULE_NAME"]);
					string sXOML        = Sql.ToString(dtFields.Rows[0]["XOML"       ]);
					if ( !Sql.IsEmptyString(sXOML) )
					{
						RuleSet rules = RulesUtil.Deserialize(sXOML);
						RuleValidation validation = new RuleValidation(typeof(SplendidReportThis), null);
						// 11/11/2010   Validate so that we can get more information on a runtime error. 
						rules.Validate(validation);
						if ( validation.Errors.HasErrors )
						{
							throw(new Exception(RulesUtil.GetValidationErrors(validation)));
						}
						foreach ( DataRow row in dt.Rows )
						{
							SplendidReportThis swThis = new SplendidReportThis(HttpContext.Current.Application, L10n, sMODULE_NAME, row);
							RuleExecution exec = new RuleExecution(validation, swThis);
							rules.Execute(exec);
						}
					}
				}
			}
		}
예제 #29
0
		public Module MODULES_MODULE_NAME_Get(string sNAME)
		{
			Module item = new Module();
			//try
			{
				if ( !(Taoqi.Security.AdminUserAccess("Modules", "list") >= 0) )
					throw(new Exception("Administrator required"));

				Taoqi.DbProviderFactory dbf = Taoqi.DbProviderFactories.GetFactory();
				using ( IDbConnection con = dbf.CreateConnection() )
				{
					con.Open();
					string sSQL;
					sSQL = "select MODULE_NAME" + ControlChars.CrLf
					     + "  from vwMODULES  " + ControlChars.CrLf
					     + " where 1 = 1      " + ControlChars.CrLf;
					using ( IDbCommand cmd = con.CreateCommand() )
					{
						cmd.CommandText = sSQL;
						// 07/12/2010   It does not make sense to allow a fuzzy search for a module name. 
						Sql.AppendParameter(cmd, sNAME, Sql.SqlFilterMode.StartsWith, "MODULE_NAME");
						// 07/02/2007   Sort is important so that the first match is selected. 
						cmd.CommandText += " order by MODULE_NAME" + ControlChars.CrLf;
						using ( IDataReader rdr = cmd.ExecuteReader(CommandBehavior.SingleRow) )
						{
							if ( rdr.Read() )
							{
								item.ID   = Sql.ToGuid   (rdr["ID"         ]);
								item.NAME = Sql.ToString (rdr["MODULE_NAME"]);
							}
						}
					}
				}
				if ( Sql.IsEmptyGuid(item.ID) )
				{
					string sCULTURE = Sql.ToString (Session["USER_SETTINGS/CULTURE"]);
					L10N L10n = new L10N(sCULTURE);
					throw(new Exception(L10n.Term("Modules.ERR_MODULE_NOT_FOUND")));
				}
			}
			//catch
			{
				// 02/04/2007   Don't catch the exception.  
				// It is a web service, so the exception will be handled properly by the AJAX framework. 
			}
			return item;
		}
예제 #30
0
			public EditViewEventManager(ListControl lstPARENT_FIELD, ListControl lstField, bool bUI_REQUIRED, int nFORMAT_ROWS, L10N L10n)
			{
				this.lstPARENT_FIELD = lstPARENT_FIELD;
				this.lstField        = lstField       ;
				this.bUI_REQUIRED    = bUI_REQUIRED   ;
				this.nFORMAT_ROWS    = nFORMAT_ROWS   ;
				this.L10n            = L10n           ;
			}