Tengo un formulario que contiene un cuadro de imagen. Cuando el formulario se carga, la imagen predeterminada se carga bien. Luego actualizo la imagen cuando algo en mi formulario cambia y cambia la imagen que se muestra. La generación de esta imagen funciona bien también, puedo ver la imagen en el disco y abrirla con pintura, etc. En general, lo que hago es abrir una secuencia de archivos en la ubicación de la imagen y luego configurar la imagen en esta ubicación.imagen de cuadro de imagen de winform muestra vacío C#
if (this.picPreview.Image != null)
{
this.picPreview.Image.Dispose();
this.picPreview.Image = null;
}
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
this.picPreview.Image = System.Drawing.Image.FromStream(fs);
Pero no importa lo que haga, la imagen aparece en blanco en el formulario. Intenté actualizar el formulario, actualizando el control de cuadro de imagen, estableciendo su propiedad visible como visible, nada ayuda.
Creo un formulario separado que contiene solo un cuadro de imagen y paso la ubicación de la imagen al formulario y repito el proceso de apertura de la transmisión y luego estableciendo la imagen en esta ubicación funciona perfectamente.
No se están produciendo excepciones AFAIK ... depurador está configurado para romper todas las excepciones.
¿Qué podría causar este comportamiento?
Cualquier consejo es apreciado. Tengo otra aplicación que genera imágenes en un hilo de fondo y eso también funciona bien.
Tal vez proporcionar más antecedentes sobre lo que estoy tratando de hacer me ayudará a llegar al fondo de esto. Para cada fila en mi vista de cuadrícula de datos hay entre una y tres columnas que tienen una imagen asociada a ellas. He generado todas estas imágenes por adelantado. Al desplazarme por la cuadrícula obtengo una imagen de vista previa de la primera columna de imagen en mi cuadro de imagen usando el evento SelectionChanged. Funciona perfectamente También tengo celdas que cuando se hace clic en mostrar una ventana de formulario con una vista previa de las imágenes que componen la imagen en el formulario principal. Esto también funciona a la perfección. Puedo cambiar las filas y hacer clic en las celdas en la cuadrícula y todo funciona. Básicamente estoy construyendo una nueva imagen basada en lo que el usuario selecciona en otros controles que están vinculados a la cuadrícula de datos.
El problema surge cuando intento cambiar la imagen en el cuadro de imagen en el formulario principal. Puedo actualizar el origen de datos y ver la actualización de los valores de la cuadrícula, pero la imagen, que ahora regenero usando un software de terceros, que puedo verificar está en el disco y se puede ver después de que la actualización se lleva a cabo, simplemente desaparece. Una vez que esto sucede, ya no obtengo una imagen en el cuadro de imagen en el formulario hasta que cierro el formulario y lo vuelvo a abrir, y luego todos los datos actualizados están allí y todo vuelve a funcionar. El código que recibe una llamada en la selección cambió para establecer que la imagen sea exactamente igual al código en el lugar para actualizar la nueva imagen. Es completamente sincrónico. Me estoy quedando sin ideas que no sea comenzar de cero con una forma completamente nueva.
Gracias de nuevo por todas las sugerencias.
Comenzaré desde la parte superior. El flujo general es el siguiente:
Abra un formulario que contiene una cuadrícula de datos que está vinculada a una vista de SQL. El dgv es de solo lectura y solo se puede seleccionar una fila a la vez. La vista se completa automáticamente, junto con los controles que están vinculados a cada columna de la cuadrícula. Estos incluyen cuadros de texto para algunos, cuadros combinados y casillas de verificación para los demás. Cada fila tiene un conjunto de imágenes asociadas. Cuando se carga el formulario, puedo desplazarme hacia abajo por la vista y para cada fila aparece una nueva imagen en el cuadro de imagen del formulario. Todas estas imágenes han sido pregeneradas. Cuando se selecciona una fila, puede haber hasta tres imágenes para la fila, en cuyo caso los botones de navegación están habilitados para permitir al usuario obtener una vista previa de cada imagen.
Seleccionar una fila, cambiar los controles en el formulario para cambiar uno o más valores de celda en la fila seleccionada.Luego presiono un botón para guardar, que actualiza la base de datos y los datos correspondientes en la grilla. Luego intento actualizar la (s) imagen (es) para esta fila. En este punto, el cuadro de imagen desaparece y pierdo las vistas previas en el formulario todos juntos; no aparecen imágenes hasta que cierro y vuelvo a abrir el formulario, y todo vuelve a estar bien hasta que guardo.
Al tratar de resolver esto, me parece que la actualización de un dgv encuadernado provoca que el evento seleccionado sea levantado varias veces. Hay un código para manejar casos donde el enlace no está completo, o no hay nada seleccionado en la vista. También hay un código en el controlador btnSave_Click para suspender el controlador de eventos de selección de cambios hasta que se complete la actualización y se regeneren las imágenes. A pesar de hacer esto, aunque la fila que actualicé se seleccionó en la vista, la fila realmente seleccionada (donde se coloca la flecha y lo que muestran todos los controles) la primera fila es siempre la fila "actual" después de la actualización. No sé cómo arreglar eso todavía. Aquí está el código para la selección modificada y el botón para guardar los manejadores de eventos.
Aquí está una captura de pantalla de la forma:
Y el código de los controladores de eventos SelectionChanged y btn_save:
/// <summary>
/// update the preview on a row selection change
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (!BindingComplete) return;
DataGridView dgv = (DataGridView)sender;
if (!dgv.Focused || dgv.CurrentRow == null) return;
// set the pic preview to the current row image(s)
// we need the record for the current index
DataRowView currentDataRowView = (DataRowView)dgv.CurrentRow.DataBoundItem;
if (currentDataRowView == null) return;
DataRow currentRow = currentDataRowView.Row;
LastSelectedIndex = dgv.SelectedRows[0].Index;
Debug.WriteLine("Current row in SelectionChanged: " + currentRow.ItemArray[0].ToString());
bool showBox = false, showProd = false, showWire = false;
string box, prod, wire;
string pdcProductName = currentRow.ItemArray[0].ToString();
showWire = !string.IsNullOrEmpty(wire = currentRow.ItemArray[7].ToString());
showBox = !string.IsNullOrEmpty(box = currentRow.ItemArray[8].ToString());
showProd = !string.IsNullOrEmpty(prod = currentRow.ItemArray[9].ToString());
// check for wirepath, box, and product. Enable the nav buttons if there is more than
// one label for this product. We need to check for LabelFileName being the same for both
// box and product, in which case there is one file for both which defaults to box
if ((showBox && showProd && prod == box) || showBox)
{
string targetFile = PreviewImagePath + pdcProductName + "_eBox.png";
if (picPreview.Image != null)
{
//picPreview.Image.Dispose();
//picPreview.Image = null;
}
// if the preview image doesn't exist yet use a default image
if (!File.Exists(targetFile))
{
// make the loading gif invisible
this.picLoading.Visible = true;
//picPreview.Image = AdminTILE.Properties.Resources.StandardPaper;
}
else
{
this.picLoading.Visible = false;
Debug.WriteLine("Opening file " + targetFile);
FileStream fs = new FileStream(targetFile, FileMode.Open, FileAccess.Read);
picPreview.Image = System.Drawing.Image.FromStream(fs);
Image imgCopy = (Image)picPreview.Image.Clone();
this.picPreview.Visible = true;
fs.Close();
// preview in another frame
if (frm.IsDisposed)
{
frm = new PreviewImage();
}
frm.PreviewLabel(imgCopy);
frm.Show();
//picPreview.ImageLocation = targetFile;
}
}
else if (showProd)
{
string targetFile = PreviewImagePath + pdcProductName + "_eBox.png";
if (picPreview.Image != null)
{
picPreview.Image.Dispose();
//picPreview.Image = null;
}
if (!File.Exists(targetFile))
{
// make the loading gif invisible
this.picLoading.Visible = true;
//picPreview.Image = AdminTILE.Properties.Resources.StandardPaper;
}
else
{
this.picLoading.Visible = false;
FileStream fs = new FileStream(targetFile, FileMode.Open, FileAccess.Read);
picPreview.Image = System.Drawing.Image.FromStream(fs);
fs.Close();
}
}
}
/// <summary>
/// update the database with the current selections
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSave_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count == 0)
{
MessageBox.Show("No record is selected to update");
return;
}
DialogResult result1 = MessageBox.Show("Saving Label Configuration. Are you sure?",
"IMPORTANT!", MessageBoxButtons.YesNoCancel);
// update the view
if (result1 == DialogResult.Yes)
{
// we need the record for the current index
DataRowView currentDataRowView = (DataRowView)dataGridView1.CurrentRow.DataBoundItem;
DataRow currentRow = currentDataRowView.Row;
string pdcProductName = currentRow.ItemArray[0].ToString();
Int32 currentIndex = dataGridView1.SelectedRows[0].Index;
Debug.WriteLine("Current index in Save:" + currentIndex.ToString());
string AgencyId="", LogoId="", WireId="";
SqlDataAdapter LabeledProductsDataTableAdapter =
new SqlDataAdapter("SELECT * FROM LabeledProducts",
printConfigTableAdapter.Connection);
SqlDataAdapter LogosDataTableAdapter =
new SqlDataAdapter("SELECT * FROM Logos",
printConfigTableAdapter.Connection);
if (vwTILEAdminTableAdapter.Connection.State != ConnectionState.Open)
{
printConfigTableAdapter.Connection.Open();
}
DataTable LogoDataTable = new DataTable();
LogosDataTableAdapter.Fill(LogoDataTable);
DataTable LabeledProductsDataTable = new DataTable();
LabeledProductsDataTableAdapter.Fill(LabeledProductsDataTable);
StringBuilder sql = new StringBuilder();
// Fill a table with the results of the
// data adapter and query the table instead of the database.
// An empty LogoDescription maps to an empty filename
DataRow dataRow;
if (cbAgency.SelectedItem != null)
{
sql.Append("LogoDescription = '").Append(cbAgency.SelectedItem).Append("'");
dataRow = LogoDataTable.Select(sql.ToString())[0];
AgencyId = dataRow.ItemArray[0].ToString();
sql.Clear();
}
if (cbPrivateLabel.SelectedItem != null)
{
sql.Append("LogoDescription = '").Append(cbPrivateLabel.SelectedItem).Append("'");
dataRow = LogoDataTable.Select(sql.ToString())[0];
LogoId = dataRow.ItemArray[0].ToString();
sql.Clear();
}
if (cbWire.SelectedItem != null)
{
sql.Append("LogoDescription = '").Append(cbWire.SelectedItem).Append("'");
dataRow = LogoDataTable.Select(sql.ToString())[0];
WireId = dataRow.ItemArray[0].ToString();
sql.Clear();
}
// PdcProductName is the primary key
sql.Append(@"UPDATE [dbo].[LabeledProducts]
SET [PdcProductName] = @pdcProd
,[LabelProductName] = @lblProd
,[LabelDescription] = @lblDesc
,[Power] = @pwr
,[Fabrication] = 0
,[UL_File_Number] = @ul
,[PrePrintedSerial] = @pps
,[ShowOrderOnLabel] = 0
,[PrivateLabelLogoId] = @plid
,[AgencyImageId] = @aid
,[WireDiagConfigId] = @wid
,[ReleasedForProduction] = @rfp
WHERE PdcProductName = '").Append(pdcProductName).Append("'");
using (SqlCommand command = new SqlCommand(sql.ToString(), vwTILEAdminTableAdapter.Connection))
{
if (vwTILEAdminTableAdapter.Connection.State != ConnectionState.Open)
vwTILEAdminTableAdapter.Connection.Open();
LabeledProductsDataTableAdapter.UpdateCommand = command;
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@pdcProd", txtPdcProdName.Text);
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@lblProd", txtLabeledProd.Text);
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@lblDesc", txtLabelDesc.Text);
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@pwr", txtPower.Text);
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@ul", txtULFileNumber.Text);
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@pps", cbPrePrintedSerial.Checked);
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@plid", LogoId);
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@aid", AgencyId);
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@wid", WireId);
LabeledProductsDataTableAdapter.UpdateCommand.Parameters.AddWithValue("@rfp", cbReleased.Checked);
//int rowsAffected = LabeledProductsDataTableAdapter.Update(LabeledProductsDataTable);
int rowsAffected = command.ExecuteNonQuery();
// The DataViewManager returned by the DefaultViewManager
// property allows you to create custom settings for each
// DataTable in the DataSet.
DataViewManager dsView = this.tILEDataSet.DefaultViewManager;
// remove the selectionChanged event handler during updates
// every update causes this handler to fire three times!!!
this.dataGridView1.SelectionChanged -= new System.EventHandler(this.dataGridView1_SelectionChanged);
dataGridView1.DataSource = typeof(TILEDataSet.vwTILEAdminDataTable);
this.vwTILEAdminBindingSource.DataSource = typeof(TILEDataSet.vwTILEAdminDataTable);
this.vwTILEAdminBindingSource.DataSource = this.tILEDataSet.vwTILEAdmin;
this.dataGridView1.DataSource = this.vwTILEAdminBindingSource;
vwTILEAdminBindingSource.ResetBindings(false); // false for data change, true for schema change
this.vwTILEAdminTableAdapter.Fill(this.tILEDataSet.vwTILEAdmin);
// we need to reget the row after the update to pass to preview
currentIndex = LastSelectedIndex;
DataGridViewRow drv = this.dataGridView1.Rows[currentIndex];
currentRow = ((DataRowView)(drv.DataBoundItem)).Row;
// update the preview files
UpdatePreviewFiles(currentRow);
// try this
dataGridView1.ClearSelection();
// this doesn't work
dataGridView1.Rows[currentIndex].Selected = true;
// reset the selection changed handler once the update is complete
this.dataGridView1.SelectionChanged += new System.EventHandler(this.dataGridView1_SelectionChanged);
}
}
}
Después de la actualización de la forma tiene el mismo aspecto, excepto el cuadro de imagen se ha ido , y los datos de la primera fila aparecen en los controles en lugar de la fila que se resalta.
Todos UpdatePreviewFiles hace es sustituir las imágenes con los actualizados. Todo lo que ShowPreview hace es establecer la imagen en el cuadro de imagen. Imagen. Todo funciona hasta que guarde/actualice.
Si hay algo más que pueda proporcionar, avíseme, esto lleva demasiado tiempo resolverlo, sé que hay una explicación relativamente simple.
Gracias de nuevo.
Dice que funciona bien en una versión simplificada. Entonces, necesitas comenzar a mirar las diferencias entre los dos. –
¿Algún propósito para usar filestream? – coder
¿Estás cerrando la transmisión? –