using System;
using System.Data;
using System.Drawing;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using $safeprojectname$.Controls;
namespace $safeprojectname$
{
///
/// User control responsible viewing, managing, and live editing the details of the movie collection.
///
///
/// Movies are added programatically by the SearchOnline control or are added manually after pressing the
/// Add button. Movies can be live edited by selecting a value in the grid. They can be deleted by selecting and pressing
/// Delete button. Press the View Online button to visit the Amazon.com Web site. Press Refresh button
/// to refresh data fields with live information from the Amazon.com Web service.
/// Movies are read from and written to MovieDatabase.mdf. It is recommended that movie information is
/// refreshed regularly.
///
public partial class ListDetails : UserControl
{
System.Windows.Forms.Form hostingForm;
//Control object responsible for rating movie titles.
//Workaround: project cannot dynamically build this custom control type
// after using New Project wizard; the control instance is created and sited at runtime instead of
// adding to design surface.
internal RatingPickerControl ratingPickerControl;
//Gets turned on, while database updates are occuring.
bool isUpdating;
///
/// Initializes this control and loads data.
///
///
/// All movie titles in the collection are loaded into the in-memory datatable;
/// The control monitors for changes to the datatable and auto saves changes made to each field.
///
private void ListDetails_Load(System.Object sender, System.EventArgs e)
{
//dynamically create rating picker control and site on the form
InitRatingPickerControl();
//listen for data changes when adding, modifying, and deleting in UI
this.dvdCollectionDataSet.DVDs.TableNewRow += new DataTableNewRowEventHandler(this.dvdCollectionDataSet.DVDs.dvdsDataTable_TableNewRow);
this.dvdCollectionDataSet.DVDs.RowChanged += new DataRowChangeEventHandler(dt_RowChanged);
//load data from database
if (this.LoadData() == 0){
//if no rows were available, create a new row so users can start entering a new dvd
this.dvdsDataConnector.AddNew();
}
this.titleTextBox.Select();
}
///
/// Detects any changes made to the datatable and saves changes to the database.
///
private void dt_RowChanged(object sender, System.Data.DataRowChangeEventArgs e)
{
if (isUpdating){
return;
}
$safeprojectname$.DVDCollectionDataSet.DVDsRow dvdDataRow = ($safeprojectname$.DVDCollectionDataSet.DVDsRow) e.Row;
if (dvdDataRow != null){
SaveData();
}
}
///
/// Creates a new movie in the collection when Add button is clicked.
///
/// It is preferable to call AddNew from the dataconnector to keep data binding between the control and datatable in sync.
private void AddTitleButton_Click(System.Object sender, System.EventArgs e)
{
this.dvdsDataConnector.AddNew();
}
///
/// Deletes the currently selected movie.
///
private void RemoveButton_Click(System.Object sender, System.EventArgs e)
{
DeleteCurrent();
}
///
/// Applies the user-specified filter when clicked.
///
private void FilterButton_Clicked(System.Object sender, System.EventArgs e)
{
ApplyTextboxFilter();
}
///
/// Applies the user-specified filter when filter string is entered.
///
private void FilterTextBox_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
ApplyTextboxFilter();
}
}
///
/// Resets DataConnector to be unfiltered when button is clicked.
///
private void ShowAllButton_Click(System.Object sender, System.EventArgs e)
{
this.dvdsDataConnector.Filter = "";
}
///
/// Refreshes the current movie selection with data from the Amazon.com Web service after prompting the user.
///
///
/// Uses UPC value to fetch the movie title from the Web service, and merges/overwrites the
/// existing data. Comments and MyRating fields are preserved as a special case.
///
private void RefreshOnlineButton_Click(System.Object sender, System.EventArgs e)
{
//prompt the user to refresh and store the result
DialogResult dialogResult = MessageBox.Show("This feature will potentially overwrite your changes. Do you want to proceed? ", "Refresh data from online Web service?", MessageBoxButtons.YesNo);
//if yes, then begin refresh process
if (dialogResult == DialogResult.Yes)
{
//object used to call Amazon.com Web service
SimpleAmazonWS amazonService = new SimpleAmazonWS();
//objects used to store search result
DVD refreshedDVD;
$safeprojectname$.DVDCollectionDataSet.DVDsRow refreshedDVDRow;
try
{
//boundary check: make sure movie datatable is not empty
if (this.dvdsDataConnector.Count > 0)
{
//gets the current movie selection and converts to a typed movie row object
DataRowView rowView = (DataRowView)this.dvdsDataConnector.Current;
$safeprojectname$.DVDCollectionDataSet.DVDsRow dvdRow = ($safeprojectname$.DVDCollectionDataSet.DVDsRow)rowView.Row;
// check to see if UPC value is null
if ((!dvdRow.IsUPCNull()) && dvdRow.UPC != "")
{
//variables to store and preserve custom comment and rating values
string currentComments = dvdRow.Comments;
int currentRating = dvdRow.MyRating;
//get updated DVD object from Web service
refreshedDVD = amazonService.RefreshDVDByUPC(dvdRow.UPC);
//update cached image
this.boxArtPictureBox.Load(refreshedDVD.ImageUrl);
refreshedDVD.ImageCache = (Bitmap)this.boxArtPictureBox.Image;
//convert DVD to dvdRow
refreshedDVDRow = this.dvdCollectionDataSet.DVDs.DVDsRowFromDVDObject(refreshedDVD);
//set the same ID as original row so row look up in the in-memory datatable succeeds
refreshedDVDRow.ID = dvdRow.ID;
//restore/merge back the custom comment and rating values
refreshedDVDRow.Comments = currentComments;
refreshedDVDRow.MyRating = currentRating;
//merge dvdRow with matching row
this.dvdCollectionDataSet.DVDs.LoadDataRow(refreshedDVDRow.ItemArray, LoadOption.Upsert);
}
}
}
catch (Exception ex)
{
MessageBox.Show(String.Format("There was a problem refreshing the data from the online Web service: {0}", ex.Message));
Debug.WriteLine(ex.ToString());
}
}
}
///
/// Navigates the to Amazon.com Web page for the current movie selection in an external browser after prompting the user.
///
/// The user should see the hyperlink before starting the browser process and navigating to the URL.
private void ViewOnlineButton_Click(System.Object sender, System.EventArgs e)
{
//boundary check: make sure movie datatable is not empty
if (this.dvdsDataConnector.Count > 0)
{
//variables to store and preserve custom comment and rating values
DataRowView rowView = (DataRowView)this.dvdsDataConnector.Current;
DVDCollectionDataSet.DVDsRow dvdRow = ($safeprojectname$.DVDCollectionDataSet.DVDsRow)rowView.Row;
//variable to store the Web page URL value
string webLink = "";
//check for null before accessing WebPageLink property
if (!dvdRow.IsWebPageLinkNull()) { webLink = dvdRow.WebPageLink; }
//prompts to see if end user trusts URL and stores the prompt result value
string msgText = String.Format("About to view this URL in an external browser: '{0}'. Is it safe to proceed?", webLink);
DialogResult yesNoResult = MessageBox.Show(msgText, "OK to browse?", MessageBoxButtons.YesNo);
//start the URL path if the user approves the prompt
if ((yesNoResult == DialogResult.Yes) && (webLink != ""))
{
Process.Start(webLink);
}
}
}
///
/// Prompts user for file to import when Clicked.
///
private void ImportButton_Click(object sender, System.EventArgs e)
{
this.openFileDialog1.ShowDialog();
}
///
/// Imports image provided by user when user clicks OK to open file prompt.
///
private void OpenFileDialog1_FileOk(System.Object sender, System.ComponentModel.CancelEventArgs e)
{
this.ImportImage(this.openFileDialog1.FileName);
}
///
/// Loads movie collection data.
///
/// Positive integer for number of rows loaded; 0 if no rows are loaded.
/// Loads movie collection data into the in-memory datatable
internal int LoadData()
{
int rowsLoaded = 0;
//try to fill the datatable with the query of all movies
//note: if the database contains a large amount of movies you'll likely want to add a query to the
//TableAdapter and only fill a subset of the movies in the database into memory.
try
{
isUpdating = true;
rowsLoaded = this.dvdsTableAdapter.Fill(this.dvdCollectionDataSet.DVDs);
}
catch (Exception ex)
{
MessageBox.Show(String.Format("There was a problem loading data: {0}", ex.Message));
Debug.WriteLine(ex.ToString());
}
finally
{
isUpdating = false;
}
return rowsLoaded;
}
///
/// Saves changes made to movie collection data.
///
/// Positive integer for number of rows updated in database; 0 if no rows are updated.
/// Saves the changes from in-memory datatable and bound UI.
internal int SaveData()
{
if (isUpdating){
return 0;
}
int rowsSaved = 0;
//try to get changes and save to database
try
{
//only push update to database if changes are detected
if (dvdCollectionDataSet.HasChanges())
{
isUpdating = true;
rowsSaved = this.dvdsTableAdapter.Update(this.dvdCollectionDataSet.DVDs);
}
}
catch
{
}
finally
{
isUpdating = false;
}
return rowsSaved;
}
///
/// Applies filter over the in-memory movie records using the user-specified input in the text box.
///
/// DataConnector object's Filter property is applied to all controls bound to the DataConnector.
private void ApplyTextboxFilter()
{
try
{
//sets filter string WHERE clause in the form "Where COLUMNNAME like '@FilterText'"
this.dvdsDataConnector.Filter = String.Format("{0} like '%{1}%'", this.dvdCollectionDataSet.DVDs.TitleColumn.ColumnName, this.filterTextBox.Text);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
///
/// Deletes the currently selected movie after prompting the user.
///
internal void DeleteCurrent()
{
//check for boundaries before performing delete: datatable is empty, or there is no selection
if ((this.dvdsDataConnector.Count > 0) && (this.dvdsDataConnector.Current != null))
//convert generic Current object returned by DataConnector to the typed movie row object
{
DataRowView rowView = (DataRowView)this.dvdsDataConnector.Current;
$safeprojectname$.DVDCollectionDataSet.DVDsRow dvdRow = ($safeprojectname$.DVDCollectionDataSet.DVDsRow)rowView.Row;
//string representing the friendly name of the current movie to be deleted
string title = "[No Title]";
//use movie title property in the typed row object if it contains valid data
if ((!dvdRow.IsTitleNull()) && (dvdRow.Title != null))
{
title = dvdRow.Title;
}
//text displayed in a prompt to the user before deleting
string msgText = String.Format("Are you sure you want to permanently delete {0} from your collection? ", title);
//display Yes/No prompt to the user and store the result
DialogResult dialogResult = MessageBox.Show(msgText, "OK to delete?", MessageBoxButtons.YesNo);
//remove the current movie if the user accepts the prompt
if (dialogResult == DialogResult.Yes)
{
this.dvdsDataConnector.RemoveCurrent();
}
//make sure we always have a row available
if (dvdsDataConnector.Count == 0){
this.dvdsDataConnector.AddNew();
}
}
}
///
/// Initializes the rating picker control used on this user control.
///
///
/// Called by ListDetails.Load event. This special initialization code is not required if the
/// RatingPickerControl is built and referenced in a separate control library.
///
private void InitRatingPickerControl()
{
//create rating picker control object and site it on the parent user control
this.ratingPickerControl = new RatingPickerControl();
this.dvdDetailsPanel.Controls.Add(this.ratingPickerControl);
//set default properties and data binding
((System.ComponentModel.ISupportInitialize)this.ratingPickerControl).BeginInit();
this.ratingPickerControl.Anchor = (System.Windows.Forms.AnchorStyles)(System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right);
this.ratingPickerControl.BackColor = System.Drawing.Color.Transparent;
this.ratingPickerControl.CurrentRating = -1;
this.ratingPickerControl.DataBindings.Add("CurrentRating", this.dvdsDataConnector, "MyRating", true, DataSourceUpdateMode.OnPropertyChanged, null);
this.ratingPickerControl.Location = new System.Drawing.Point(128, 388);
this.ratingPickerControl.Name = "RatingPickerControl1";
this.ratingPickerControl.Size = new System.Drawing.Size(80, 16);
this.ratingPickerControl.TabIndex = 7;
((System.ComponentModel.ISupportInitialize)this.ratingPickerControl).EndInit();
}
///
/// Imports image value into datatable from file provided by user.
///
///
private void ImportImage(string filename)
{
try
{
//check for boundaries before performing delete: datatable is empty, or there is no selection
if (this.dvdsDataConnector.Current != null)
{
//convert generic Current object returned by DataConnector to the typed movie row object
DataRowView rowView = (DataRowView)this.dvdsDataConnector.Current;
$safeprojectname$.DVDCollectionDataSet.DVDsRow dvdRow = ($safeprojectname$.DVDCollectionDataSet.DVDsRow)rowView.Row;
//open file as Readonly from file system, copy bytes, and assign to the image property of the current row
dvdRow.ImageBinary = File.ReadAllBytes(filename);
this.dvdsDataConnector.ResetCurrentItem();
}
}
catch (Exception ex)
{
MessageBox.Show(String.Format("There was a problem loading the image: {0}", ex.Message));
Debug.WriteLine(ex.ToString());
}
}
private void HostingForm_FormClosed(System.Object sender, System.Windows.Forms.FormClosedEventArgs e){
//call EndEdit to capture all changes made in the UI
this.dvdsDataConnector.EndEdit();
//when the parent form is closing, be sure to save the data on this control
SaveData();
}
private void ListDetails_ParentChanged(System.Object sender, System.EventArgs e){
////if the parent form for this user control ever changes we need to reset the Form_Closed event handler for the new parent form
if (hostingForm != null){
this.hostingForm.FormClosed -= new System.Windows.Forms.FormClosedEventHandler(HostingForm_FormClosed);
}
this.hostingForm = (System.Windows.Forms.Form)this.ParentForm;
this.hostingForm.FormClosed += new System.Windows.Forms.FormClosedEventHandler(HostingForm_FormClosed);
}
private void TitleTextBox_Click(System.Object sender, System.EventArgs e){
if (this.titleTextBox.Text == "[New row - select to enter details]"){
this.titleTextBox.SelectAll();
}
}
}
}