Mam formularz, który zawiera obrazek. Kiedy formularz wczytuje domyślny obraz ładuje się dobrze. Następnie aktualizuję obraz, gdy zmieni się coś w mojej formie, które zmienia wyświetlany obraz. Generowanie tego obrazu działa również dobrze, widzę obraz na dysku i otwieram go za pomocą farby itp. Ogólnie rzecz biorąc, robię to, otwierając strumień plików w lokalizacji obrazu, a następnie ustawiając obraz w tej lokalizacji.WinForm obrazka pokazuje pusty 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);
Ale bez względu na to, co robię, obraz pojawia się pusty na formularzu. Próbowałem odświeżenie formularza, odświeżenie kontrolki graficznej, ustawienie widocznej właściwości na widoczną, nic nie pomaga.
Tworzę oddzielny formularz, który zawiera tylko obrazek i przekazuje lokalizację obrazu do formularza i powtórzyć proces otwierania strumienia, a następnie ustawienie obrazu w tym miejscu działa idealnie.
Nie ma żadnych wyjątków podczas rzucania AFAIK ... debugger jest ustawiony na łamanie wszystkich wyjątków.
Co może powodować takie zachowanie?
Każda rada jest doceniana. Mam kolejną aplikację, która generuje obrazy w wątku pracującym w tle i to też działa dobrze.
Zapewnienie większej ilości informacji o tym, co próbuję zrobić, pomoże mi dojść do sedna. Dla każdego wiersza w moim datagridview znajduje się między jedną a trzema kolumnami, do których przypisany jest obraz. Z góry wygenerowałem wszystkie te obrazy. Przewijanie siatki Otrzymuję obraz podglądu pierwszej kolumny obrazu w moim polu graficznym za pomocą zdarzenia SelectionChanged. Działa idealnie. Mam również komórki, które po kliknięciu pokazują okno formularza z podglądem obrazów, które składają się na obraz w głównym formularzu. To również działa doskonale. Mogę zmienić wiersze i kliknąć komórki w siatce i wszystko działa. Zasadniczo buduję nowy obraz w oparciu o to, co wybiera użytkownik na innych kontrolkach, które są związane z datagridem.
Problem pojawia się, gdy próbuję zmienić obraz w ramce graficznej na formularzu głównym. Mogę zaktualizować źródło danych i zobaczyć aktualizację wartości siatki, ale obraz, który teraz zregeneruję za pomocą oprogramowania innej firmy, który mogę zweryfikować na dysku i jest widoczny po aktualizacji, po prostu znika. Kiedy to nastąpi, nie otrzymuję już obrazu w ramce graficznej w formularzu, dopóki nie zamknę formularza i nie otworzę go ponownie, a następnie wszystkie zaktualizowane dane są dostępne i wszystko działa ponownie. Kod, który zostanie wywołany przy wyborze, zmieniony tak, aby ustawić obraz jest dokładnie taki sam jak kod w miejscu, aby zaktualizować nowy obraz. Jest całkowicie synchroniczny. Brakuje mi pomysłów innych niż zaczynanie od zera z zupełnie nową formą.
Jeszcze raz dziękuję za wszystkie sugestie.
Zacznę od góry. Ogólny przepływ jest następujący:
Otwórz formularz zawierający datagrid powiązany z widokiem SQL. Dgv jest tylko do odczytu i tylko jeden wiersz może być wybrany na raz. Widok wypełnia się automatycznie wraz z kontrolkami, które są powiązane z każdą kolumną siatki. Należą do nich pola tekstowe dla niektórych, comboboxes i checkboxy dla pozostałych. Każdy wiersz zawiera skojarzony z nim zestaw obrazów. Po załadowaniu formularza mogę przewinąć widok, a dla każdego wiersza w polu graficznym w formularzu pojawi się nowy obraz. Wszystkie te obrazy zostały wstępnie wygenerowane. Po wybraniu wiersza w wierszu może znajdować się maksymalnie trzy obrazy, w którym to przypadku przyciski nawigacyjne są włączone, aby umożliwić użytkownikowi podgląd każdego obrazu.
Wybieram wiersz, zmieniam formanty w formularzu, aby zmienić jedną lub więcej wartości komórki w wybranym wierszu.Następnie kliknąłem przycisk zapisu, który aktualizuje bazę danych i odpowiednie dane w siatce. Następnie próbuję zaktualizować obrazy dla tego wiersza. W tym momencie ramka graficzna znika i tracę podglądy w formularzu razem; żadne obrazy nie pojawiają się, dopóki nie zamknę i ponownie nie otworzę formularza, a wszystko będzie dobrze, dopóki nie zrobię zapisu.
Próbując rozwiązać ten problem, stwierdzam, że aktualizacja powiązanego dgv powoduje wielokrotne wywołanie zdarzenia selectchanged. Istnieje kod obsługujący przypadki, w których powiązanie nie jest kompletne lub w widoku nie ma niczego wybranego. Istnieje również kod w procedurze obsługi btnSave_Click, który zawiesza procedurę obsługi zdarzeń "changechanged", aż do zakończenia aktualizacji i ponownego wygenerowania obrazu (ów). Pomimo tego, mimo że wybrany wiersz jest aktualizowany w widoku, faktycznie wybrany wiersz (gdzie znajduje się strzałka i co wszystkie kontrolki wyświetlają), pierwszy wiersz jest zawsze "bieżącym" wierszem po aktualizacji. Nie wiem jak to naprawić. Oto kod dla zmiany selekcji i przyciski obsługi zdarzeń zapisywania przycisków.
Oto zrzut ekranu w postaci:
I kod dla SelectionChanged i btn_save obsługi zdarzeń:
/// <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);
}
}
}
Po aktualizacji postać wygląda tak samo z wyjątkiem skrzynka obraz zniknął , a dane z pierwszego wiersza są wyświetlane w kontrolkach, a nie w podświetlonym wierszu.
Wszystkie UpdatePreviewFiles robi to zastąpić obrazy ze zaktualizowanymi nich. Wszystko, co robi ShowPreview, to ustawienie obrazu w obrazku. Obraz. Wszystko działa, dopóki nie zrobię zapisu/aktualizacji.
Jeśli jest coś jeszcze, co mogę dostarczyć, daj mi znać, to zajmie zbyt dużo czasu, aby rozwiązać, wiem, że istnieje stosunkowo proste wyjaśnienie.
Jeszcze raz dziękuję.
Mówisz, że działa poprawnie w uproszczonej wersji. Musisz więc zacząć przyglądać się różnicom między nimi. –
Każdy cel używania filestream? – coder
Czy zamykasz strumień? –