Power Builder - Nuevo Tip - DropDownDW con checkbox

   
Vista:

Nuevo Tip - DropDownDW con checkbox

Publicado por Jeinner Hidalgo jhidalgo@excelteccr.com (638 intervenciones) el 15/06/2015 23:04:30
Otra pequeña ayuda, de la forma más simple que pueda crear.

La idea sería poder tener un campo en el DW, el cual sea de tipo DropDownDW, pero que al presionarlo, para ver la lista de opciones, se presente una en la que se puedan escoger múltiples opciones. Algo como esto:

(Por favor use su imaginación)
Campo DropDown [\/]
+-------------------------+ <- Suponga que esta es la lista de Checkboxs
| Opcion Check1 [X] |
| Opción Check2 [ - ] |
| Opcion Check3 [ - ] |
|-------- [ APLICAR ]--|
+-------------------------+

Aclarando lo que vamos a hacer. Tenemos un DW Padre y sobre este pondremos otro que será Hijo. Al presionar el ratón sobre el Campo_DDDW en el Padre, se activará el otro DW Hijo, que estará sobre el anterior.

Para este ejemplo, tendremos un campo en el DW Padre, el cual llamaré Campo_DDDW, en este se deberán mostrar separados por comas los códigos que se checkeen de la lista en el DW Hijo.
En el DW Hijo que será de tipo Grid External tendremos tres campos:
s_Codigo_Llave String(10)
s_Descripcion String(100)
s_Campo_Check String(1)

1. Agregue las siguientes funciones generales a su programa:
Función f_Hilera_Dividir_Vector - toma una hilera dividida por algún caracter y la separa en campos de un vector.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
global type f_hilera_dividir_vector from function_object
end type
 
forward prototypes
global function integer f_hilera_dividir_vector (string as_hilera, ref string as_hilera_vector[], string as_caracter_division)
end prototypes
 
global function integer f_hilera_dividir_vector (string as_hilera, ref string as_hilera_vector[], string as_caracter_division);Integer li_cantidad_divisiones, &
		  li_contador, &
		  li_posicion
 
 
 
If Right(RightTrim(as_hilera), Len(as_caracter_division)) <> as_caracter_division Then &
	as_hilera+=as_caracter_division
 
li_cantidad_divisiones=f_Hilera_Contar_Coincidencias(as_hilera, as_caracter_division)
For li_contador=1 to li_cantidad_divisiones
	li_posicion=Pos(as_hilera, as_caracter_division)
	as_hilera_vector[li_contador]=Left(as_hilera, li_posicion - 1)
	as_hilera=Right(as_hilera, len(as_hilera) - li_posicion)
Next
 
RETURN li_cantidad_divisiones
end function

Función f_SetRow - Asignar una lista de valores a los campos de un DW.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
global type f_setrow from function_object
end type
 
forward prototypes
global function integer f_setrow (ref datawindow adw_referencia, string as_nombre_columna, integer ai_fila_inicial, integer ai_fila_final, any aav_valores[])
end prototypes
 
global function integer f_setrow (ref datawindow adw_referencia, string as_nombre_columna, integer ai_fila_inicial, integer ai_fila_final, any aav_valores[]);Integer li_RegistrosActualizar, &
        li_Nodo, &
		  li_Ultimo, &
		  li_Resultado
 
 
 
// Calcular Cantidad de Registros a Actualizar.
li_RegistrosActualizar=(ai_Fila_Final - ai_Fila_Inicial)+1
 
// Completar Lista de Valores a Actualizar.
If UpperBound(aav_Valores) <> li_RegistrosActualizar Then
	li_Ultimo=UpperBound(aav_Valores)
	For li_Nodo=1 to li_RegistrosActualizar
		aav_Valores[li_Nodo]=aav_Valores[li_Ultimo]
	Next
End If
 
For li_Nodo=ai_Fila_Inicial to ai_Fila_Final
	li_Resultado=adw_Referencia.SetItem(li_Nodo, as_Nombre_Columna, aav_Valores[ai_Fila_Inicial - (ai_Fila_Inicial -1)])
	If li_Resultado <> 1 Then &
		EXIT
Next
 
RETURN li_Resultado
end function

Función f_GetDWStatus - Obtener el estado general del DW.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
global type f_getdwstatus from function_object
end type
 
forward prototypes
global function dwitemstatus f_getdwstatus (ref datawindow adw_revisar, dwbuffer adwb_revisar)
end prototypes
 
global function dwitemstatus f_getdwstatus (ref datawindow adw_revisar, dwbuffer adwb_revisar);DWItemStatus ldwis_1
Integer li_Registro, &
        li_Total_Registros=0
 
 
 
ldwis_1=NOTMODIFIED!
li_Total_Registros=adw_Revisar.RowCount()
For li_Registro=1 to li_Total_Registros
	ldwis_1=adw_Revisar.GetItemStatus(li_Registro, 0, adwb_Revisar)
	If ldwis_1 = NEWMODIFIED! or ldwis_1 = DATAMODIFIED! Then &
		RETURN ldwis_1
Next
 
RETURN NOTMODIFIED!
end function

2. Ya en materia; debemos indicar que el Campo_DDDW en el DW Padre, tendrá que presentarse de forma visual, con las características de un DropDown, para esto agregue el siguiente código al evento Constructor del DW padre:
1
2
3
Modify("Campo_DDDW.DDLB.limit=0 "+ &
	    "Campo_DDDW.DDLB.AllowEdit=Yes "+ &
	    "Campo_DDDW.DDLB.UseAsBorder=Yes ")

También podría hacerlo de forma directa editando el DW, bastaría con indicarle que el campo es un DropDownDW en las propiedades de la carpeta Edit.

3. Usted deberá crear su propio DW (para el DW Hijo, para este ejemplo ya indiqué qué campos va a contener), el cual tendrá las opciones que deseamos sean mostradas con los Check, decidiendo si la información que debe visualizar el usuario, proviene de una tabla o de una lista "manual". Podemos agregar un botón de ACEPTAR, en la barra de Footer, para que siempre esté visible. Dicho botón, nos ayudará a salvar los cambios que sean realizados por el usuario.

4. Ahora, cree un control DW en la ventana, al cual le asignaremos el nuevo DW que acabamos de hacer en el punto anterior. Lo posicionaremos de forma visual, sobre el DW Padre, directamente abajo del campo que queremos haga el efecto buscado. De igual forma que se ven los DropdownDW.

5. En el evento DropDown del DW Padre, deberá incluir código, para evitar que se despliegue la caja con la lista de opciones, cuando sea escogido el Campo_DDDW
1
2
If GetColumnName() = 'Campo_DDDW' Then &
	RETURN 1

6. Deberá crear la variable de instancia idwo_ObjetoClicked y en el evento Clicked del DW Padre indique:
1
idwo_ObjetoClicked=dwo

7. Como queremos que el comportamiento del DW Hijo, sea el mismo que el del un DDDW normal, necesitaremos que al perder el foco del DW Padre se cierre el hijo. Por ello, deberá añadir el siguiente código al evento ItemFocusChanged del DW Padre:
1
2
3
4
5
6
If dwo.Name = 'Campo_DDDW' Then
	dw_Hijo.Visible=TRUE
 
Else
	dw_Hijo.Visible=FALSE
End If

8. Cree el Evento ue_Activar, sin parámetros y sin retorno, en el DW Hijo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Integer li_PrimerRegistroPagina, &
        li_UltimoRegistroPagina, &
		  li_Registro, &
		  li_PosicionY, &
		  li_Total_Nodos, &
		  li_Registro_Marcar
String lsv_Nodos[]
 
 
li_PrimerRegistroPagina=Integer(dw_Aportaciones.Describe("DataWindow.FirstRowOnPage"))
li_UltimoRegistroPagina=Integer(dw_Aportaciones.Describe("DataWindow.LastRowOnPage"))
li_Registro=dw_Aportaciones.GetRow()
 
li_PosicionY=(li_Registro - li_PrimerRegistroPagina)*68
 
// Ajustar Posición Del DW Con la Lista de Checks.
Y=236+li_PosicionY
 
// Desmarcar Todos Los Registros.
f_SetRow(dw_Hijo, 's_Campo_Check', 1, RowCount(), {'N'})
AcceptText()
Sort()
 
// Marcar Registros.
If Len(String(dw_Padre.Object.Campo_DDDW[dw_Padre.GetRow()])) > 0 Then
	li_Total_Nodos=f_Hilera_Dividir_Vector(dw_Padre.Object.Campo_DDDW[dw_Padre.GetRow()], lsv_Nodos, ',')
	For li_Registro=1 to li_Total_Nodos
		li_Registro_Marcar=Find("Trim(s_Codigo_Llave) = Trim('"+String(lsv_Nodos[li_Registro])+"')", 1, RowCount())
		SetItem(li_Registro_Marcar, 'Marca', 'S')
	Next
	AcceptText()
End If
 
ResetUpdate()
 
Sort()
SetRow(1)
ScrollToRow(1)
SetFocus()
Visible=TRUE

9. Para asegurarnos que se active y se muestre el DW Hijo, agregue el siguiente código en el evento LButtonUp del Padre:
1
2
3
4
5
6
7
8
9
10
11
12
If Not IsNull(idwo_ObjetoClicked) Then
	If idwo_ObjetoClicked.Name = 'campo_dddw' Then
		If Not dw_Hijo.Visible Then
			dw_Hijo.Event ue_Activar()
			SetNull(idwo_ObjetoClicked)
			RETURN
		End If
	End If
End If
 
dw_Hijo.Visible=FALSE
SetNull(idwo_ObjetoClicked)

9. Cuando el usuario presione el botón ACEPTAR, dentro del DW Hijo, haremos que el Campo_DDDW del padre, muestre todas los códigos que hayan sido checkeadas por el usuario, con el siguiente código que agregaremos en el evento Buttonclicked:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Integer li_Registro
String ls_Marcas
 
If f_GetDWStatus(dw_Hijo, PRIMARY!) = DATAMODIFIED! Then
	If Messagebox('Consulta', 'Está seguro de querer Aplicar los cambios?', Question!, YesNo!, 2) = 1 Then &
	   ls_Marcas=''
	    For li_Registro=1 to RowCount()
	        If Object.s_Campo_Check[li_Registro] = 'S' Then &
		   ls_Marcas+=IIf(ls_Marcas <> '', ', ', '')+Object.s_Codigo_Llave[li_Registro]
	    Next
 
	dw_Padre.Object.Campo_DDDW[dw_Padre.GetRow()]=ls_Marcas
	dw_Padre.AcceptText()
 
	Visible=FALSE
 
Else
	Visible=FALSE
End If

10. No olvidemos agregar el código para ocultar el DW Hijo, en el constructor de este indique:
1
Visible=FALSE


Las limitaciones de este código son:
a. No sirve para DW muy largos, en los cuales para poder visualizar el campo DDDW, con la lista de checks, haya que desplazar el scroll hacia la izquierda.
b. Si el DW tiene propiedades de resize para las columnas o de mover las mismas, esto también dará al traste con el Tip.

Claro las limitaciones anteriores tienen solución, pero requieren de que usted hagas las pruebas y agregue el código necesario.

A ver si les es útil. Provecho.

Saludos.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder