C# WPF Adding items to listview keeps overwriting existing data - c#

I am fairly new to C#. I have a MainWindow which contains a ListView (lvStores), furthermore, I have a button that will open another window (NewStoreWindow). The NewStoreWindow contains 2 textboxes and an OK button. When I write something in the textboxes and press OK, the window is is rightfully closing and adding to my ListView. However, when I try to add a new item to the ListView, after adding the first, it will just overwrite it. Or actually, it will remove it, and then it will add the next one. I believe it has to do with my ObservableCollection. I have tried to put them in my public MainWindow() but then the code wouldn't execute. Furthermore, I have tried to use List instead of ObservableCollection.
Snippet of MainWindow code
private void cmdNewStore_Click(object sender, RoutedEventArgs e)
{
if (m_blnBusy)
{
return;
}
// Open NewStoreWindow in a new window
NewStoreWindow newStore = new NewStoreWindow();
newStore.ShowDialog();
ObservableCollection<AddListViewItem> lvColumnList = new ObservableCollection<AddListViewItem>();
ObservableCollection<AddListViewItem> items = (ObservableCollection<AddListViewItem>)lvStores.ItemsSource;
lvStores.ItemsSource = lvColumnList;
switch (SLvCol)
{
// If CSV is NOT loaded on start up and listview is then empty
case false:
// If no items exist in listview
if (items == null)
{
// Add item from textbox from NewStoreWindow
lvColumnList.Add(new AddListViewItem() {sID = SNewStoreTbid, sName = SNewStoreTbName});
lvStores.ItemsSource = lvColumnList;
// Refresh listview
lvStores.Items.Refresh();
}
else // If items exists
{
if (items != null)
{
bool itemAlreadyAdded = false; // use for boolean checking
foreach (AddListViewItem item in items) // loop through all items in listview
{
//Do some work with the item
MessageBox.Show(item.sID);
if (item.sID == SNewStoreTbid) // Check if new item already exists
{
itemAlreadyAdded = true;
break;
}
if (itemAlreadyAdded) // Show messagebox if it exists
{
MessageBox.Show("ID needs to be unique, please respecify!", "Duplicate ID",
MessageBoxButton.OK, MessageBoxImage.Error);
}
else // if it does not exist, create it from the textbox values
{
lvColumnList.Add(
new AddListViewItem() {sID = SNewStoreTbid, sName = SNewStoreTbName});
lvStores.ItemsSource = lvColumnList;
// refresh listview
//ICollectionView view = CollectionViewSource.GetDefaultView((List<AddListViewItem>)lvStores.ItemsSource);
//view.Refresh();
lvStores.Items.Refresh();
}
}
}
}
break;
.....
}
// Bind textbox values from NewStoreWindow
public class AddListViewItem
{
public string sID { get; set; }
public string sName { get; set; }
}
AddListViewItem item = new AddListViewItem
{
sID = SNewStoreTbid, //SNewStoreTbid,
sName = SNewStoreTbName //SNewStoreTbName
};

Related

DataGridView not loading data programmatically

I am working on a Windows application where I get an input from a TextBox and add it to the DataGridView when user clicks on a Button (Add).
My problem is that when I add the text for the first time, it works fine and its added to the grid.
When I add new text, it's not added to the DataGridView. Once the Form is closed and reopened with the same object then I am able to see it.
Code:
private void btnAddInput_Click(object sender, EventArgs e)
{
if (Data == null)
Data = new List<Inputs>();
if (!string.IsNullOrWhiteSpace(txtInput.Text))
{
Data.Insert(Data.Count, new Inputs()
{
Name = txtInput.Text,
Value = string.Empty
});
}
else
{
MessageBox.Show("Please enter parameter value", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
txtInput.Text = "";
gridViewInputs.DataSource = Data;
}
I am not sure what is causing the record not to be added to grid on second add button click.
You could set the DataGridView.DataSource to null before setting a new one.
This would cause the DataGridView to refresh its content with the new data in the source List<Inputs>:
the underlying DataGridViewDataConnection is reset only when the DataSource reference is different from the current or is set to null.
Note that when you reset the DataSource, the RowsRemoved event is raised multiple times (once for each row removed).
I suggest to change the List to a BindingList, because any change to the List will be reflected automatically and because it will allow to remove rows from the DataGridView if/when required: using a List<T> as DataSource will not allow to remove a row.
BindingList<Inputs> InputData = new BindingList<Inputs>();
You can always set the AllowUserToDeleteRows and AllowUserToAddRows properties to false if you don't want your Users to tamper with the grid content.
For example:
public class Inputs
{
public string Name { get; set; }
public string Value { get; set; }
}
internal BindingList<Inputs> InputData = new BindingList<Inputs>();
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.DataSource = InputData;
}
private void btnAddInput_Click(object sender, EventArgs e)
{
string textValue = txtInput.Text.Trim();
if (!string.IsNullOrEmpty(textValue))
{
InputData.Add(new Inputs() {
Name = textValue,
Value = "[Whatever this is]"
});
txtInput.Text = "";
}
else
{
MessageBox.Show("Not a valid value");
}
}
If you want to keep using a List<T>, add the code required to reset the DataGridView.DataSource:
private void btnAddInput_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(textValue))
{
//(...)
dataGridView1.DataSource = null;
dataGridView1.DataSource = InputData;
txtInput.Text = "";
}
//(...)

Getting selected rows of report files from a WPF Datagrid on button click

This is my first question on stackoverflow and I am entirely new to programming in C# so please bear with me. I created an application using WPF in which I displayed a list of files with .rpt extension in a datagrid. The datagrid contains the list of filenames and there is also a checkbox column in the datagrid. These files are populated in the grid dynamically from a folder browser when I click on a button. I am stuck on the part of retreiving these files for printing when I click on a second button (print, as I need to call a service to print the selected files).
This is the code snippet that I have tried until now:
public partial class MainWindow : Window
{
public class ReportFile
{
public string Path { get; set; }
public string FileName { get; set; }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
string inputPath = AppDomain.CurrentDomain.BaseDirectory;
System.Windows.Forms.FolderBrowserDialog fldDlg = new System.Windows.Forms.FolderBrowserDialog();
fldDlg.SelectedPath = AppDomain.CurrentDomain.BaseDirectory;
DialogResult result = fldDlg.ShowDialog();
foreach (string str in Directory.GetFiles(fldDlg.SelectedPath))
{
ReportFile reportFile = new ReportFile();
reportFile.Path = str;
reportFile.FileName = System.IO.Path.GetFileName(str);
dataGrid1.Items.Add(reportFile);
}
}
private void button_Click_1(object sender, RoutedEventArgs e)
{
foreach (ReportFile drv in dataGrid1.SelectedItems.OfType<ReportFile>())
{
if (drv != null)
{
DataRow row = drv.Row;
Title = row.ItemArray[3].ToString();
System.Windows.MessageBox.Show(Title.ToString());
}
}
var TransactionFactory = new TransactionFactory();
var Transaction = TransactionFactory.NewTransactionString();
var EnvironmentValue = (string)cmbEnvironment.SelectedValue;
var CirieEngineServiceClientFactory = new CirieEngineServiceClientFactory(EnvironmentValue);
var CirieEngineServiceClient = CirieEngineServiceClientFactory.NewCirieEngineServiceClient();
var Form = new Cirie.Form()
{
Path = string.Empty,
Title = string.Empty
};
var PackageID = Convert.ToInt16(txtPackageID.SelectedText);
var Generation = Convert.ToInt16(txtGeneration.SelectedText);
var formList = new List<Cirie.Form>();
var stream = CirieEngineServiceClient.PrintFormCollection
(Transaction,
new Collection<Cirie.Form>(formList),
PackageID,
Generation
);
}
}
But I am not sure if it is correct since there is an exception being thrown: Unable to cast object of type 'ReportFile' to type 'System.Data.DataRowView'
I would really appreciate help on this one please!
You could use the OfType method to cast the SelectedItems to ReportFile objects and then access any properties of the ReportFile class:
foreach (ReportFile drv in dataGrid1.SelectedItems.OfType<ReportFile>())
{
//...
}

NotifyDatasetChanged() to update Listview from server

I have a ListView whose items are fetched from an Api call. Then I add another item , send it to api to add it. I want to update the existing list with the value I just added.
I am doing something like this:-
itemList = dataAgent.GetItemList(some params);
cAdapter = new ItemsListAdapter(this, itemList);
lvItems.Visibility = ViewStates.Visible;
lvItems.Adapter = cAdapter;
SetListViewHeightBasedOnChildren(lvItems);
}
btnItemComment.Click += btnItemComment_Click;
void btnItemComment_Click(object sender, EventArgs e)
{
string itemsText = editComments.Text.ToString().Trim();
if(string.IsNullOrEmpty(itemsText))
{
CreateAndShowAlert(this, "", "Please enter a text");
}
else
{
var status = dataAgent.PostItem (Some more params);
if(status)
{
cAdapter.NotifyDataSetChanged();
}
}
}
But the ListView does not get refreshed. Is there anything else I need to do? Any help would be appreciated
Set adapter again and then add NotifyDataSetChanged:-
cAdapter = new ItemsListAdapter(this, itemList);
cAdapter.NotifyDataSetChanged();

How to pass data between forms?

I am developing a desktop application in which I want to get information from user. If user selects particular radio button then I am opening a new form in popup in which I have placed checked list box. After selecting values from check box I want to access selected value in the previous form. Below are images that can clear idea.
When user click on radio button in "Enable conent type" (as highlighted in the screen) a new form in popup is open to select values from checked list box. After selecting desired value , press "Select" button from Select Content Type form.
Now the form will be hidden but I want to get the selected values in the form "Create Lists".
My code for Radio Button event is:
private void rdbEnableCtypeYes_CheckedChanged(object sender, EventArgs e)
{
if (rdbEnableCtypeYes.Checked)
{
lblSelectContentType.Visible = true;
frmSelectContentType selectContentType = new frmSelectContentType();
selectContentType.rootWebUrl = rootWebUrl;
selectContentType.MdiParent = this.MdiParent;
selectContentType.StartPosition = FormStartPosition.CenterScreen;
selectContentType.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
selectContentType.Show();
}
else
{
lblSelectContentType.Visible = false;
cmbContentType.Visible = false;
}
}
My code for form of Select content type is:
public string rootWebUrl = string.Empty;
XDocument contentTypeFile = XDocument.Load(FilePaths.ContentTypesFilePath);
private void frmSelectContentType_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(rootWebUrl))
{
if (contentTypeFile != null)
{
XElement xSiteCollection = contentTypeFile.Descendants(XmlElements.SiteCollection).Where(x => x.Attribute(XmlAttributes.Url).Value.Equals(rootWebUrl)).FirstOrDefault();
if (xSiteCollection != null)
{
IEnumerable<XElement> xContentTypes = xSiteCollection.Descendants(XmlElements.ContentType);
if (xContentTypes.OfType<XElement>().Count() > 0)
{
foreach (XElement xContentType in xContentTypes)
{
ComboboxItem item = new ComboboxItem();
item.Text = xContentType.Attribute(XmlAttributes.Name).Value;
item.Value = xContentType.Attribute(XmlAttributes.Id).Value;
lstContenType.Items.Add(item);
}
}
}
}
}
}
What should I do?
Try This.
Select Content Type Form
private List<string> _selectedItems = new List<String>();
public List<string> SelectedItem
{
get {return _selectedItems;}
}
private void btnSelect_Click(object sender, EventArgs e)
{
for(int i=0; i<lst.Items.Count;i++)
{
if (lstContenType.GetItemCheckState(i) == CheckState.Checked)
_selectedItems.Add(lst.Items[i].ToString());
}
this.Close();
}
Create List Form
private void rdoEnableCntType_Checked(object sender, EventArgs e)
{
if (rdoEnableCntType.Checked = true)
{
FrmConentType frm = new FrmConentType();
frm.ShowDialog();
List<string> list = frm.SelectedItems;
//Place your code to use selected items
}
}
You can pass data in the Constructor of FormB. For example:
//Default Constructor
public FormB()
{
InitializeComponent();
}
// Overloaded Constructor
public FormB(string parameter1, string parameter2, string parameter3)
{
InitializeComponent();
}
For example:
public FormB(bool RbuttonChecked)
{
InitializeComponent();
if(RbuttonChecked)
{
//Code
}
}
Invoke FormB from FormA like:
FormB obj=new FormB(Rbtn.checked); //Invoking the overloaded constructor
obj.Show();
You can defined a list in the main form to store items user selected in "Select Content Type" windows. When user have finished the window "Select Content Type", you add selected items to the variable.
In Form "Create List" class:
public List<ContentType> selectedContentTypes = new List<ContentType>();
When user press "Select" button in form "Select Content Type", add items to the variable:
// For each selected items in the listbxo {
frmCreateList.selectedContentTypes.Items.Add(itemId);
// }
If you can post your source code, it would be easier to help.

Maintaning my choices on GridView Checkbox

I have this Module in my project in which I have 2 gridviews. One is for the Main MenuModule and the other one is for it's subMenu. I created a List so that when a row on my Main Menu Module has been checked and it has a corresponding submenu, it will show on the SubMenu Gridview.
Now, I can see my SubMenuGridview when I get back to that page (I used session), but I noticed that the checkbox I ticked were all gone.
My problem was on how can my page remember the checkboxes I checked, both from my Main Menu Module gridview and from my Submenu gridview.
protected void cbxSelect_CheckedChanged(object sender, EventArgs e)
{
SubMenuGrid.DataSource = null;
SubMenuGrid.DataBind();
Business.SubMenuModules sub = new Business.SubMenuModules();
List<oSubList> oList = new List<oSubList>();
int counter = 0;
foreach (GridViewRow nRow in gvModuleList.Rows)
{
Int32 intModID = Convert.ToInt32(nRow.Cells[0].Text);
CheckBox chkBx = (CheckBox)nRow.FindControl("cbxSelect");
if (chkBx.Checked == true)
{
counter = counter + 1;
var oModList = sub.GetAllMenuPerModuleID(intModID);
if (oModList.Count > 0)
{
foreach (var rec in oModList)
{
oSubList olist = new oSubList
{
ID = rec.ID,
ModuleID = rec.ModuleID,
Submenu = rec.Submenu,
Description = rec.Description
};
oList.Add(olist);
}
Session["list"]=oList;
SubMenuGrid.DataSource = oList;
SubMenuGrid.DataBind();
}
}
}
}
This can be done using:
ViewState
SessionPageStatePersister
Custom Session based solution
For view state-see the below posted link in comments..
Custom Session based solution
We are going to use the pre render method.
This method is being invoked after the page has been initialized but before it saved its ViewState and rendered.
Are are going to load the Request.Form into a session variable and load it back with each call to the page that is not a postback.
protected void Page_PreRender(object sender, EventArgs e)
{
if (!Page.IsPostBack && Session["PageState"] != null)
{
NameValueCollection formValues = (NameValueCollection)Session["PageState"];
String[] keysArray = formValues.AllKeys;
for (int i = 0; i < keysArray.Length; i++)
{
Control currentControl = Page.FindControl(keysArray[i]);
if (currentControl != null)
{
if (currentControl.GetType() == typeof(System.Web.UI.WebControls.TextBox)) ((TextBox)currentControl).Text = formValues[keysArray[i]];
else if (currentControl.GetType() == typeof(System.Web.UI.WebControls.CheckBox))
{
if (formValues[keysArray[i]].Equals("on")) ((CheckBox)currentControl).Checked = true;
}
else if (currentControl.GetType() == typeof(System.Web.UI.WebControls.DropDownList))
((DropDownList)currentControl).SelectedValue = formValues[keysArray[i]].Trim();
}
}
}
if(Page.IsPostBack) Session["PageState"] = Request.Form;
}
SessionPageStatePersister
The abstract PageStatePersister class represents the base class that encapsulates the Page State storage and processing.
Storage can be done with the default HiddenFieldPageStatePersister class or with SessionPageStatePersister.
When SessionPageStatePersister is used, the .NET Server manages the _VIEWSTATE in a session object instead of a hidden field on your form.
Changing the state storage looks like this:
protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(this);
}
}

Categories