Formulario de datos

08/08/2006 - 20:11 por Francisco Garzon | Informe spam
Hola grupo, saludos a todos.

Estoy intentando realizar mi primer programa en serio con el vb.net, he
contruido un formulario para acceder a la tabla de clientes de una base de
datos llamada GESTION. Os explico un poco como lo estoy haciendo y despues
os muestro mi problema:

Tengo el siguiente codigo en el evento Load:

strConn = "Server=(Local);DataBase=GESTION;Integrated Security=SSPI"
Dim CNN As New SqlConnection(strConn)

Dim strSQL As String = "SELECT * FROM Customers"
Dim scmd As New SqlCommand(strSQL, CNN)

sda = New SqlDataAdapter(scmd)

Dim scb As New SqlCommandBuilder(sda)
sda.InsertCommand = scb.GetInsertCommand()
sda.UpdateCommand = scb.GetUpdateCommand()
sda.DeleteCommand = scb.GetDeleteCommand()

dsPrincipal = New DataSet()
sda.Fill(dsPrincipal, "Customers")
dtPrincipal = dsPrincipal.Tables(0)

txtID.DataBindings.Add("Text", dtPrincipal, "ID")
txtApellidos.DataBindings.Add("Text", dtPrincipal, "Apellidos")
txtNombre.DataBindings.Add("Text", dtPrincipal, "Nombre")


Para moverme por los registros utilizo botones con el codigos:

Me.BindingContext(dtPrincipal).Position -= 1

ó

Me.BindingContext(dtPrincipal).Position += 1


Para actualizar:

Me.BindingContext(dtPrincipal).EndCurrentEdit()
sda.Update(dtPrincipal)

Para Cancelar:

Me.BindingContext(dtPrincipal).CancelCurrentEdit()
sda.Update(dtPrincipal)


Y todo hasta aqui bien, modifico los textbox y cuando ejecuto el boton
actualizar o cancelar me funciona perfectamente.

En cambio para crear un nuevo registro utilizo lo siguiente:

Me.BindingContext(dtPrincipal).AddNew()

se me limpian los textbox y tecleo los nuevos datos completos. Al pulsar el
boton de actualizar con el codigo que hemos visto antes me salta una
excepcion indicandome que el campo ID es obligatorio y no puede contener
null, borrandome el que yo habia tecleado.

Alguien me puede decir que estoy haciendo mal, y si existe una forma mejor
de hacer los que estoy haciendo, que no sea con el asistente para acceso a
datos, por favor que me lo diga.


Otra pregunta, ¿Para que sirven las siguientes lineas, ya que si las quito
tambien funciona?, ¿Son necesarias?

Dim scb As New SqlCommandBuilder(sda)
sda.InsertCommand = scb.GetInsertCommand()
sda.UpdateCommand = scb.GetUpdateCommand()
sda.DeleteCommand = scb.GetDeleteCommand()

Tambien me gustaria saber que debo ejecutar cuando cierre el formulario y
cerrar todos las conexiones abiertas, dataadapter, dataset, datatable, ...

Como siempre, muchisimas gracias de antemano.

Saludos

Preguntas similare

Leer las respuestas

#11 SoftJaén
17/08/2006 - 17:18 | Informe spam
"Francisco" escribió:

Ya he averiguado donde estaba el problema, aunque todavia no lo he
solucionado.

El problema parece que esta en que no funciona bien la herencia en este
caso.
El formulario que tenia era de clientes, y estaba heredado desde un
formulario base, donde realizo las operaciones con BindingContext. Se ve
que para desplazarse por los registros funciona bien, pero no tanto cuando
creas un nuevo registro e intentas actualizarlo.

¿Es diferente el bindingcontext del formulario padre y del hijo?, ¿como
debo referenciar cada uno?



Pues entiendo que la propiedad BindingContext, tanto del formulario base
como del formulario heredado, son la misma, porque dicha propiedad lo único
que hace es administrar la colección de objetos BindingManagerBase
existentes en el formulario.

Pero digo yo que, si en el formulario base tienes los típicos botones de
navegación, los cuales aumentan o disminuyen el valor de la propiedad
«Position» de un objeto BindingManagerBase, y a dicho objeto le has asignado
la propiedad «BindingContext» del formulario (a la cual le has tenido que
pasar un objeto DataSet), para enlazar los controles de texto del formulario
heredado al objeto BindingManagerBase del formulario base, el objeto DataSet
lo tienes que declarar en el formulario base con un ámbito de visibilidad
distinto a «Private», como bien podría ser «Protected». Me explico:

- Formulario Base:

A nivel del formulario base, tienes las siguientes declaraciones de
variables objeto:

Private bmb As BindingManagerBase
Protected ds As DataSet

En el evento Load creas el objeto DataSet y le asignas la propiedad
«BindingContext» al objeto BindingManagerBase:

bmb = Me.BindingContext(ds, "Clientes")

Por supuesto, se entiende que en el formulario base tienes los cuatro
botones para navegar por el conjunto de datos (primero, anterior, siguiente,
último).

- Formulario Heredado:

En el formulario heredado tienes los controles de texto, los cuales quieres
enlazarlos con el objeto DataSet del formulario base. Pues en el evento Load
del formulario heredado, ejecutarías lo siguiente:

' Procedemos a enlazar los controles de texto
txtIdCliente.DataBindings.Add("Text", MyBase.ds, "Clientes.IdCliente")
txtNombre.DataBindings.Add("Text", MyBase.ds, "Clientes.Nombre")

Observa que para indicar el origen de datos de los controles de texto,
utilizo la palabra clave «MyBase», de esta forma referencio al objeto
DataSet existente en el formulario base, declarado como «Protected», o con
otro ámbito distinto a «Private».

El problema esta solo en campos que son claves principales, ya que si le
indicaba que era autonumerico entonces va bien, pero no era lo que yo
necesitaba. Necesito permitir que el usuario indique el codigo que desee.



Ya te indiqué que una clave principal no admite valores duplicados o nulos,
por lo que en tu código tienes que controlar los valores que se le van a
asignar al campo que forma la clave principal, encerrando el código de
actualización entre un bloque Try ... End Try, para detectar las posibles
excepciones que puedan ocurrir, y actuar en consecuencia.

Me surge una pregunta: Cuando se define un dataSet y se rellena con una
tabla, este no coge que campos son clave.
Entonces cuando acepto un registro, y despues de lanzar el metodo update
del dataset, si la clave esta duplicada, salta el mensaje de infraccion de
primarykey, el registro no se graba en la base de datos, pero la fila si
se queda en el DataSet. ¿Que codigo debo de poner que compruebe que es
nuevo y que al dar el error eliminar esa fila devolviendo la posicion a la
ultima correcta?



Si en el formulario base tienes el código para llamar al método Update del
objeto DataAdapter, una vez que se produzca la excepción, puedes moverte a
una fila en concreto, de igual manera que si pulsaras un botón de
navegación:

Try
' Código de actualización
'

Catch ex As Exception
' Si se produce una excepción, nos movemos
' a la última fila
bmb.Position = bmb.Count - 1

End Try


Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Respuesta Responder a este mensaje
#12 Francisco
18/08/2006 - 09:15 | Informe spam
Hola Enrique:

De la manera que me dices es como tengo definido el dataset a nivel del
formulario padre, lo unico que no tengo igual es la referencia al MyBase al
enlazar los controles de texto.

Pero aun asi me funcionaba todo a excepcion de cuando aceptaba un registro
nuevo, que entiendo que me devolviese un error null, ya que el codigo es
PrimaryKey y por supuesto no admite null, el tema es que cuando el
formulario es hijo, se ve que los campos clave no los enlaza bien, ya que
los campos clave no los modifica, ya que aunque se especifique el valor
nuevo del campo clave en la caja de texto, cuando lo aceptas, pasa
totalmente de el, y lo cambia por el valor anterior, en el caso de nuevo:
blanco, y para un registro existente, el valor anterior al cambio. En
principio lo detecte solo al graba uno nuevo, pero luego hize mas pruebas y
detecte que no cambia la clave ni en los registros existentes. En cambio si
el formulario lo hago exactamente igual pero sin herencia, osea todo en el
mismo formulario, funciona todo perfectamente.

Es verdad que es conveniente declarar una clave clave primaria al datatable
para que la excepcion se detecte al aceptar el dataset con EndEdit, ya que
de no hacerlo la excepcion salta cuando se acepta el dataadapter y en este
caso no se graba en la base de datos, pero si se ha grabado en el dataset.

Tengo tres nuevas preguntas:

¿Como se define una clave con varios segmentos, osea, por ejemplo que la
clave principal fuera empresa+orden?

¿Como referencio las cajas de texto declaradas en el formulario hijo desde
el padre? ¿Existe una coleccion controls como en VB6?

¿Conoces algun link de un buen ejemplo de impresion de datos, por pantalla e
impresora, desde VB.NET?

Muchas Gracias
Saludos.
Respuesta Responder a este mensaje
#13 SoftJaén
18/08/2006 - 17:51 | Informe spam
"Francisco" preguntó:

¿Como se define una clave con varios segmentos, osea, por ejemplo que la
clave principal fuera empresa+orden?



¿Donde deseas definir la clave principal que agrupe varios campos? ¿En la
tabla de la base de SQL Server, o en un objeto DataTable?

¿Como referencio las cajas de texto declaradas en el formulario hijo desde
el padre? ¿Existe una coleccion controls como en VB6?



Si estás trabajando con un formulario heredado, entiendo que no hay ningún
formulario "padre" e "hijo". Existe el formulario base y el formulario
heredado, pero no hay ninguna relación padre-hijo, por lo que ignoro cómo
puedes referenciar desde el formulario base, los controles de texto
existentes en el formulario heredado.

Existe el concepto de formularios MDI (formulario contenedor o padre) y
formularios MDI hijos, pero en este caso, no existe herencia alguna entre
ambos formularios o clases.

Si un formulario hereda de otro, como con cualquier otra clase de objeto que
se puede heredar, se suele trabajar con la clase derivada, la cual heredará
toda la interfaz perteneciente a la clase (o formulario) base, y podrás
extender la clase o formulario heredado, con nuevos campos, propiedades y
métodos, pero todos estos nuevos miembros pertenecen a la clase heredada, no
a la clase de la cual se ha derivado previamente: la clase base.

Podrás trabajar en tu aplicación también, si así lo deseas, con el
formulario base, como si fuera un formulario más existente en el proyecto, y
podras llamar a los controles existentes en el formulario heredado, de igual
forma que llamarías a cualquier propiedad pública exiente en el mismo,
siempre y cuando el ámbito de visibilidad del control sea distinto a
Protected o Private:

Dim frm As FormHeredado
frm.TextBox1.Text = "¡Hola, Mundo!"
frm.Show ()

¿Conoces algun link de un buen ejemplo de impresion de datos, por pantalla
e impresora, desde VB.NET?



No, lo siento. Para esta última pregunta, te sugeriría que iniciaras un
nuevo mensaje, por si los restantes compañeros del grupo de noticias conocen
algún ejemplo que te pudiera servir.

Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Respuesta Responder a este mensaje
#14 Francisco
21/08/2006 - 08:45 | Informe spam
Hola:

¿Como se define una clave con varios segmentos, osea, por ejemplo que la
clave principal fuera empresa+orden?




Me refiero dentro de un datatable, el ejemplo que me pusistes fue solo de un
segmento de clave.

¿Como referencio las cajas de texto declaradas en el formulario hijo
desde
el padre? ¿Existe una coleccion controls como en VB6?



Si estás trabajando con un formulario heredado, entiendo que no hay ningún
formulario "padre" e "hijo". Existe el formulario base y el formulario
heredado, pero no hay ninguna relación padre-hijo, por lo que ignoro cómo
puedes referenciar desde el formulario base, los controles de texto
existentes en el formulario heredado.



Entonces no hay forma de recorrer los controles desde una funcion del
formulario base en tiempo de ejecucion y que se pueda acceder a todos los
controles incluidos los del formulario heredado. Entiendo la herencia, pero
quisiera saber si llega un poco mas y en tiempo de ejecucion se comportan
como un formulario. Entonces para crear funciones o metodos donde se acceda
a los controles del formulario heredado desde el formulario base, tendre que
pasarle como parametro el propio formulario heredado, ¿o conoces otra forma?
¿se puede definir un control para que su ambito de visibilidad llegue al
formulario base, sin que sea publico al proyecto?, ¿como?

Espero coincidir algun dia por nuestra tierra.

Muchas Gracias.
Saludos

Francisco Garzon
Jaén (Spain)
Respuesta Responder a este mensaje
#15 SoftJaén
21/08/2006 - 14:25 | Informe spam
"Francisco" escribió:

Me refiero dentro de un datatable



Si deseas que la clave principal del objeto DataTable esté formada por dos
campos, deberás de crear una matriz de objetos DataColumn para asignársela a
la propiedad «PrimaryKey» del objeto DataTable.

Aquí tienes un ejemplo, que prácticamente está calcado del que aparece en la
ayuda de la propiedad «PrimaryKey», pero que en lugar de crear y añadir
nuevas columnas al objeto DataTable, toma dos columnas ya existentes en
dicho objeto, en tu caso, las columnas «Empresa» y «Orden»:

Private Sub SetPrimaryKey(ByVal dt As DataTable)

' Vamos a establecer dos objetos DataColumn que
' actuarán de clave primaria del objeto DataTable.
'
Dim keys(1) As DataColumn
Dim column As DataColumn

Try
' Referenciamos la primera columna.
'
column = dt.Columns("Empresa")

' Añadimos la columna al array.
'
keys(0) = column

' Referenciamos la segunda columna.
'
column = dt.Columns("Orden")

' Añadimos la columna al array.
'
keys(1) = column

' Con el valor del array, establecemos la propiedad PrimaryKey.
'
dt.PrimaryKey = keys

Catch ex As Exception
MessageBox.Show(ex.Message)

End Try

End Sub

Ni que decir tiene que ambos campos no deberán tener valores nulos, porque
de lo contrario, obtendrás la oportuna excepción.

Si posteriormente deseas comprobar los campos que conforman la clave
principal, puedes llamar al siguiente procedimiento, pasándole el objeto
DataTable:

Private Sub GetPrimaryKeys(ByVal table As DataTable)

' Creamos el array para las columnas
Dim columns() As DataColumn
columns = table.PrimaryKey

' Obtenemos el números de elementos del array.
Console.WriteLine("Número Columnas: " & columns.Length.ToString())
Dim n As Integer
For n = 0 To columns.GetUpperBound(0)
Console.WriteLine(columns(n).ColumnName & _
" -> " & columns(n).DataType.ToString())
Next
End Sub

Entonces no hay forma de recorrer los controles desde una función del
formulario base en tiempo de ejecución y que se pueda acceder a todos los
controles incluidos los del formulario heredado.



La colección de controles de un formulario en concreto, la puedes recorrer
de la misma forma que se hacía en Visual Basic 6.0. Pero como ya te indiqué
en mi mensaje anterior, ignoro cómo puedes recorrer desde el formulario
base, la colección de controles de un formulario heredado. Si fuera al
revés, no había ningún problema, porque harías referencia al formulario base
mediante la palabra clave «MyBase», tal y como se muestra en el siguiente
ejemplo:


Dim ctrl As Control

' Recorremos la colección Controls del
' formulario base.
'
For Each ctrl In MyBase.Controls
MessageBox.Show(ctrl.Name)
Next

Como también te indiqué, la única manera que conozco para recorrer la
colección Controls del formulario heredado desde el formulario base, es que
trates al formulario heredado como si fuera otro formulario cualquiera:

Dim frm As New FormularioHeredado
Dim ctrl As Control

' Recorremos la colección Controls del
' supuesto formulario heredado.
'
For Each ctrl In frm.Controls
MessageBox.Show(ctrl.Name)
Next

¿Se puede definir un control para que su ambito de visibilidad llegue al
formulario base, sin que sea publico al proyecto?



¡Vamos a ver! Según mis conocimientos, la herencia parte de una clase
llamada «clase base», y se van creando nuevas clases a partir de la misma,
las llamadas «clases derivadas», podiéndose referenciar la clase base
mediante la palabra clave «MyBase», pero nunca al contrario, salvo que yo
esté equivocado.

Para conocer desde la supuesta clase base, los objetos contenidos en una
clase derivada de aquella, el ámbito de visibilidad de los controles y
objetos incluidos en la clase derivada, deberá ser distinto a Private o
Protected. Por ejemplo, si deseas que un control sea accesible desde todas
las clases contenidas en un ensamblado, deberás declarar el control, como
mínimo, con un ámbito de visibilidad Friend, y accederías al mismo desde el
formulario base, de igual manera que accederías a cualquier control incluido
en otro formulario con igual ámbito de visibilidad, con independencia que
éste sea heredado o no:

Dim frm As New FormularioHeredado

' Leemos el nombre del control ListBox
' existente en el formulario heredado,
' el cual está declarado como Friend.
'
MessageBox.Show(frm.ListBox1.Name)

Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida