Datagrid View in a form gets populated from a List
I have this Form with a datagridview that gets populated from a List.
When i click on the Users button on each row, a list of users also in a datagrid should appear
The datagrid on the new form gets updated by the list i pass, When i click on the Users button this is what happens:
GetUserDescriptorDetails gtUserDetails = new GetUserDescriptorDetails(name, xmlData, CreateListDynamically(name));
gtUserDetails.ShowDialog();
the CreateListDynamically method is like this:
public BindingList<xml.UserDescriptor> CreateListDynamically(string _name)
{
foreach (xml.UserDescriptor dbList in xmlData.Users)
{
if (dbList.DatabaseDescriptorName == _name)
{
users.Add(new xml.UserDescriptor() { DatabaseDescriptorName = dbList.DatabaseDescriptorName, Username = dbList.Username, Password = dbList.Password, IsAdmin = dbList.IsAdmin });
}
}
return users;
}
Now the list is fine, but every time i click on the Users button the rows duplicate, because of the users.Add. How can i solve this?
The fact that i add values is only to populate the list, is there any other way to get the list with the condition:
dbList.DatabaseDescriptorName == _name
Inside your CreateListDynamically(string _name) method, you are never clearing the previous users list, this will be why you are getting the duplication.
Add a users.Clear() before your foreach loop and the duplication should go away.
This all ofc assumes that users is a class variable since I do not see it being passed into the method as a variable
What you could also do is entirely decouple the users variable and just have a temporary variable for your resultset inside your method:
public BindingList<UserDescriptor> CreateListDynamically(string _name)
{
return new BindingList<UserDescriptor>(xmlData.Users.FindAll(x => x.DatabaseDescriptorName == _name));
}
Related
I have a project where a user can add new products or modify existing ones. Products can have parts associated with them. I created a list in the class where my product constructor lives to hold parts for each product.
I'm trying to figure out how to set up that if a user makes changes to the parts that are associated with a product but hits the cancel button then the list reverts to the original list. If they hit the save button after making edits to the products parts list then the updated list is saved and when they open the product again then the updated list displays.
All the code in the file I have is quite a bit but the parts I thought would be most helpful for what I have are...
Filling in the product text boxes with the information on the product. Populating the datagridview CurrentPartsDataGrid with the tempParts list that is a copy of the product.Parts list. Or creating a new empty list if it's a new product that is created.
if (product != null)
{
ProductIdText.Text = product.ID.ToString();
ProductNameText.Text = product.Name.ToString();
InvText.Text = product.QOH.ToString();
PriceText.Text = product.Price.ToString();
InvMinText.Text = product.Min.ToString();
InvMaxText.Text = product.Max.ToString();
tempParts = new BindingList<Part>(product.Parts);
}
else
{
product = new Product();
tempParts = new BindingList<Part>();
}
CurrentPartsDataGrid.DataSource = tempParts;
In the save/cancel button click event methods I have tried doing a for loop or for each loop. I clear the list and then try to repopulate.
Code in save
product.Parts.Clear();
foreach (Part part in tempParts)
{
product.Parts.Add(part);
}
Code in Cancel
tempParts.Clear();
foreach (Part part in product.Parts)
{
tempParts.Add(part);
}
If there is anything else that would be helpful, let me know. I'm new to posting here so don't want to overload the post but also don't want to not provide enough.
Any help on how to fix this would be awesome.
Thanks!
I ended up not needing to do any of the EndEdit() stuff.
In my (if product != null)
I added
tempList = new BindingList<Part>();
for (int i = 0; i < product.Parts.Count; i++)
{
tempList.Add(product.Parts[i]);
}
This created a new templist that when the user selected cancel I set product.Parts = tempList which resolved the issue.
hi i have question for remove data from 2 forms dialog
in first dialogform it's contain list of data, and in second dialogform it's contain detail of data and delete button... i already successfully delete data in database but i confused how to remove data from list...
if just select data and delete i know it's can be done with this code
quizzes.RemoveAt(listBoxQuizzes.SelectedIndex);
but problem here in dialogform1 not available button delete, just view details data. so if user want to delete data, he must open dialogform2 (detail data)
i already done delete data in database with this code
Global.deleteData("DELETE FROM Quiz_Occurrences WHERE ID = " + id);
and close detaildataform (dialogform2) by
this.Close();
and move to dialogform1 (listdatabox)
the problem in here, data which just i delete still in there because it's still not remove yet (already delete from database but not remove from list). and need to restart program to see effect of delete data
Update Progress
i changed data to global var, so it's technically i can remove data in dialogform2
this is code (modifier listbox in dialogform1)
int no = 1;
foreach (CQuizOccurrence myQuizOccurrence in Global.quizOccurrences) {
}
if i want to delete it from dialogform1, i can use
Global.quizOccurrences.removeAT(listBoxQuizzes.SelectedIndex);
but if i want to delete it from dialogform2
Global.quizOccurrences.removeAT(.........); //still not have idea how can i reference index
Update solution from #nitin
so first i write in formdialog2
public Frmdialog1 frm_dialog { get; set; }
then i write this in formdialog1
frmdialog2.frm_dialog=this;
then back again to formdialog1 to write
frm_dialog.quizzes.RemoveAt(frm_dialog.listBoxQuizzes.SelectedIndex);
is that right because i get many error
If you are opening second dialog from first one u can Have property in Frmdialog2 like
public Frmdialog1 frm_dialog { get; set; }
After creating object of Frmdialog2 in Frmdialog1 you can set this property as
frmdialog2.frm_dialog=this;
Now u can remove item from this listbox in Frmdialog2 iteself after deleting record from database as
frm_dialog.quizzes.RemoveAt(frm_dialog.listBoxQuizzes.SelectedIndex);
NOTE: Modifier for your listbox should be public
i'm finally be able to do as i want after ask many different question about this topic
first i try to change var to global, so i can remove data in listbox dialogform1 from dialogform2 (i think it's the easiest way)
//in dialog form1
foreach (CQuizOccurrence myQuizOccurrence in Global.quizOccurrences) {
//load data from Global.quizOccurences
}
//call function close to close dialogform1
then in dialogform2, match Global.quizOccurrences data with date&time detail data (using list & foreach)
List<CQuizOccurrence> matchData = new List<CQuizOccurrence>();
foreach (CQuizOccurrence myQuizOccurrence in Global.quizOccurrences)
{
DateTime dtDatabase = (DateTime)myQuizOccurrence.occurred;
string dt = dtDatabase.ToString();
if (dt == dateOccur) {
matchData.Add(myQuizOccurrence);
}
}
foreach (CQuizOccurrence myQuizOccurrence in matchData)
{
Global.quizOccurrences.Remove(myQuizOccurrence);
}
//call function show dialog for formdialog1
form1 could subscibe to the form2's close event.
inside form1
form2 f2dialog = new form2(/*I guess you are passing data here*/);
f2.dialog.Closing += eventhandler;
somewhere else
void eventhandler(object sender, eventargs e)
{
//refresh globaldata since by now you have ran delete query
//rebind or call listbox.items.refresh() or both <-------------this how do you get data from rver? the server is updated but does global know that?
}
then you need to call code to get data from database again. and rebind to data
listbox.datacontext = Global.GetData();//or however this is done
you have to manually reset this eveerytime you change your database
databinding is not as smart as you think it is.
I am looking to see if it is possible to be able to increment an ObservableCollectionevery time a button is clicked?
ObservableCollection<string> _title = new ObservableCollection<string>();
public ObservableCollection<string> Title
{
get { return _title; }
set
{
_title = value;
OnPropertyChanged(() => Title);
}
}
As shown from the C# code above, I have an ObservableCollection for a Title. Currently, when I add a new title, every title goes into the same collection. However, what I am aiming to achieve is; every time the "Add Title" button is pressed, a new title is added and a new ObservableCollection is created. Is this possible, and how can it be done?
EDIT1
At the moment I dynamically create Textboxes and then add whatever string I want to that Textbox. From there I save the Stackpanel, named 'Content', into a .txt file. In this file it will hold the Textboxs that have been created. (It does not save the string into that file due to the textbox being binded). I then thought the strings would be saved into a list, and when I load the Stackpanel back up from the .txt file the string would get added back to the Textbox.
EDIT2
I have changed a bit of code:
public ViewModel()
{
this.AddTitleCommand = new RelayCommand(new Action<object>((o) => OnAddTitle()));
}
private void OnAddTitle()
{
NewTitle += titleName;
}
When doing this it is not adding my string as a word it is separating the letters in my string in separate titles.
If I understand you correctly, each time your Button is pressed, you want to add a new string into a new collection. You then said that you will add other values into each collection... this sounds like you're trying to fulfil your requirements in the wrong way, but you didn't tell us what those were, so we can't help you with that. Here's how you can add a new collection each time:
private string newTitle = string.Empty;
private ObservableCollection<ObservableCollection<string>> collections = new
ObservableCollection<ObservableCollection<string>>();
public ObservableCollection<ObservableCollection<string>> Collections
{
get { return collections; }
set { collections = value; OnPropertyChanged(() => Collections); }
}
public string NewTitle
{
get { return newTitle; }
set { newTitle = value; OnPropertyChanged(() => NewTitle); }
}
public void AddCollection()
{
ObservableCollection<string> collection = new ObservableCollection<string>();
collection.Add(NewTitle);
Collections.Add(collection);
}
The NewTitle property could be data bound to a TextBox in the UI allowing users to enter the new values and when the Button is pressed, the AddCollection method would add it into a new collection and then add that into the Collections collection.
I still think that this is not a good idea though.
UPDATE >>>
Please stop what you're doing... programs are not written like that. We save data, the strings, not UI elements. There is absolutely no point in saving the UI elements along with all their extra property values that you have no interest in. Whatever method you have of displaying the strings in the TextBoxes can be reused each time the data is loaded.
ObservableCollection provides a constructor that takes an IEnumerable so use it to create a new instance with the same titles and add your new title afterward :
ObservableCollection<string> newCollection = new ObservableCollection<string>(Title);
newCollection.Add(theNewTitle)
Title = newCollection;
I have an aspx page which has the following:
A repeater with a linkbutton in each
The link button has a commandargument of an integer value
A user control
The idea is that when the user clicks on the linkbutton the value of the commandarguement is stored in a List. No problem you may think, however I need the value to be stored in an List in the usercontrol, not in the ASPX page. The List needs to be persisted across postbacks, so it also needs to be stored in the viewstate.
So I created a public property in the user control like so:
public List<int> ImageString {
get {
if (this.ViewState["ImageString"] != null) {
return (List<int>)(this.ViewState["ImageString"]);
}
return new List<int>();
}
set { this.ViewState["ImageString"] = value; }
}
And then I was hoping that from my aspx page I could add a line of code to add a value to the list like so:
this.LightBoxControl.ImageString.Add(value);
The problem I'm getting is that the the value is actually never added to the list. The count is always zero.
I'm sure its just that I've set the property up wrong, but I'm not sure how to right it..
Any help would be greatly appreciated.
Thanks
Al
Your getter is wrong. This is the correct variant:
get {
if (this.ViewState["ImageString"] == null) {
this.ViewState["ImageString"] = new List<int>();
}
return (List<int>)(this.ViewState["ImageString"]);
}
Here you first check whether there is something you need in ViewState already, and if there is no, you add it there. Then you return the item from ViewState - it is guaranteed to be there.
Your solution was bad because it did not place new List<int>() into the ViewState
I try solve this problem. In WFP app I bind binadble collection to the property ItemSource of listBox.
Property signature is:
public BindableCollection<UserInfo> Friends
{
get { return _friends; }
set
{
_friends = value;
NotifyOfPropertyChange(() => Friends);
}
}
UserInfo class consit property:
BitmapImage ProfilePhoto {get;set;}
String Nick{get;set}
String Status{get;set;} //offline, online, chatting
String ChatRoom{get;set;} //name of chat room where user chatting
I get every 10 seconds new fresh data as IDictionary => ().
I need refresh data in listbox. So I try this:
private void RefreshContactsData(IEnumerable<KeyValuePair<string, UserInfo>> freshFriends)
{
//store selected item in listBox
var tempSelectedFriend = SelectedFriend;
//store selecte index in listbox
var tempSelectedIndex = SelectedFriendsIndex;
//Clear property which is binded on listBox ItemSource
Friends.Clear();
foreach (var freshFriend in freshFriends)
{
freshFriend.Value.IsFriend = true;
//Add fresh data
Friends.Add(freshFriend.Value);
}
StayInRoom();
//set
SelectedFriend = tempSelectedFriend;
SelectedFriendsIndex = tempSelectedIndex;
}
Problems is:
I store current current selected item in listBox, clear listbox, add new data, and set back selected item in listbox.
But user see that scrollbar is moved and moved back and also selected item flashed.
How can I remove this unwanted behavior.
I expect that the issue is your SelectedFriend property refers to a reference which no longer exists when your collection is repopulated. Is there any property on UserInfo which uniquely identifies a user? (Nick?). You could store this selected value instead, and then after repopulating the collection, find and set SelectedFriend to the item whose Nick matches the stored value.
To prevent listbox scrollbar jumping do not remove then add back all items from the BindableCollection.
Rewrite RefreshContactsData to:
Delete items that exist in Friends that no longer exist in freshFriends.
Add items that exist in freshFriends that do not exist in Friends.
Update existing items in Friends and freshFriends.
You may need to implement INotifyPropertyChanged on UserInfo.