I am trying to add some data inside my DataGrid.
I added some columns with the designer. Now I want to add rows with data inside the DataGrid.
Here's my code so far:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var dataContext = new PurchaseOrderDataContext();
var purchaseOrderTable = dataContext.GetTable<PurchaseOrder>();
var query = from a in purchaseOrderTable
select a;
var purchaseOrders = query;
foreach (var purchaseOrder in purchaseOrders)
{
// I believe that this method is the right one, but what do I pass to it?
// dataGrid1.Items.Add(test);
}
}
All I want to know is: What kind of object do I need to use to add something in the DataGrid, and what kind of object do I need to pass to that last method? Also how do I add, let's say, text to a certain column of a row I added?
Thanks a lot!
In general, you would bind the ItemsSource of the grid to a collection that supports change notification (IObservableCollection is idea) and just add to the collection. If the collection supports change notification, the grid will automatically display the new row.
Try this:
dataGrid1.ItemsSource = query;
Related
I have two windows wpf.
On the first window I see data from DataGrid, on the second window I delete object from database.
First window:
private void mnRemoveProduct_Click(object sender, RoutedEventArgs e)
{
RemoveProduct window = new RemoveProduct();
window.ShowDialog();
ShowWatchTable();
} // mnRemoveProduct_Click
Second window:
private void btnDelete_Click(object sender, RoutedEventArgs e)
{
if (cmbNameOfWatch.SelectedIndex > 0)
{
var value =
(from watch in obj.Watch.Where(w => w.mark == cmbNameOfWatch.SelectedValue.ToString())
select new { watch.id }).ToArray().First();
Watch watchObj = obj.Watch.Find(value.id);
obj.Watch.Remove(watchObj);
obj.SaveChanges();
this.Close();
}
} // btnDelete_Click
and function ShowTable
public void ShowWatchTable()
{
obj.Watch.ToList();
dataGrid.ItemsSource =
from watch in obj.Watch.Local
select new
{
ID = watch.id,
Brand = watch.mark,
Typ = watch.TypeWatch.typeName,
Price = watch.price + " $".ToString(),
Quantity = watch.number,
Fabricator = watch.Fabricator.fName,
Country = watch.Fabricator.Country.countryName
};
}
When I delete value from database, I still see this value in DataGrid. Only when I close and open this form then I no longer see this object. When I add an element, the same logic is used. Datagrid is updated with the ShowTable function and I see the updated database. But when deleting it it does not work. Please help
From what I can see, you are deleting from obj.Watch using
obj.Watch.Remove(watchObj);
obj.SaveChanges();
but when refreshing your list, you are binding to obj.Watch.Local which I assume is a local cache of your datasource. I don't see where you are syncing this so you might want to sync that before binding or perform your operations on the local sync and ensure that it sends it's changes to the remote data source.
Well, my guess your data source is a query result, but i'm not pretty sure that it's observable(f.e. when I need to bind to collections, I use IObservableCollection to notify that collection changed).
Probably you can try to call dbGrid.Items.Refresh(); method when your primary views gets focus back
You just need to manually refresh your DataGrid.
Add this after your datasource is updated:
dataGrid.Items.Refresh();
You should make sure the collection backing the source of your data items implements INotifyCollectionChanged.
MSDN link to docs, also copied relevant section here.
Binding to Data
To bind the DataGrid to data, set the ItemsSource property to an IEnumerable implementation. Each row in the data grid is bound to an object in the data source, and each column in the data grid is bound to a property of the data object. In order for the DataGrid user interface to update automatically when items are added to or removed from the source data, the DataGrid must be bound to a collection that implements the INotifyCollectionChanged interface, such as an ObservableCollection. To automatically reflect property changes, the objects in the source collection must implement the INotifyPropertyChanged interface. For more information, see Data Binding (WPF).
I set this DataBindingComplete event to my datagridview. I want every datasource that binding to datagridview can be sortable by clicking on column.
void MakeColumnsSortable_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
DataGridView dataGridView = sender as DataGridView;
foreach (DataGridViewColumn column in dataGridView.Columns)
column.SortMode = DataGridViewColumnSortMode.Automatic;
}
all of my datasource is List and bindingsource doesnot sort when my list is ended by .ToList
Now . how can i convert datagridview.datasource to Equin.ApplicationFramework.BindingListView and set it again to datasource for make any datagridview sortable?
Proper usage of Equin.ApplicationFramework.BindingListView would be as follows
Upon creation of your form:
Create a BindingListView. It will be filled later with the items that you want to display / sort / filter
Create a BindingSource.
Create a DataGridView.
Add the columns to the properties you want to show
The latter three steps can be done in visual studio designer. If you do that, The code will be in InitializeComponents.
Suppose you want to show / sort / filter elements of MyType Your form will be like:
public class MyForm : Form
{
private BindingListView<MyType> MyItems {get; set;}
public MyForm()
{
InitializeComponent();
this.MyItems = new BindingListView<MyType>(this.components);
// components is created in InitializeComponents
this.MyBindingSource.DataSource = this.MyItems;
this.MyDataGridView.DataSource = this.MyBindingSource;
// assigning the DataPropertyNames of the columns can be done in the designer,
// however doing it the following way helps you to detect errors at compile time
// instead of at run time
this.columnPropertyA = nameof(MyType.PropertyA);
this.columnPropertyB = nameof(MyType.PropertyB);
...
}
You can do without the BindingSource, you can assign the BindingListViewdirectly to the DataSource of the DataGridView. Sorting and Filtering will still work. However the BindingSource will help you to access the currently selected item.
private MyType SelectedItem
{
get {return ((ObjectView<MyType>)this.MyBindingSource.Current)?.Object; }
}
private void DisplayItems (IEnumerable<MyType> itemsToDisplay)
{
this.MyItems.DataSource = itemsToDisplay.ToList();
this.MyItems.Refresh(); // this will update the DataGridView
}
private IEnumerable<MyType> DisplayedItems
{
get {return this.MyItems; }
// BindingListview<T> implements IEnumerable<T>
}
This is all. You don't need to create special functions to sort on mouse clicks. The sorting will be done automatically inclusive deciding on the sort order and displaying the correct sorting glyphs. If you want to sort programmatically:
// sort columnPropertyA in descending order:
this.MyDataGridView.Sort(this.columnPropertyA.ListsortDirection.Descending);
One of the nice things about the BindingListView is the filtering option:
// show only items where PropertyA not null:
this.MyItems.ApplyFilter(myItem => myItem.PropertyA != null);
// remove the filter:
this.MyItems.RemoveFilter();
(I'm not sure if a Refresh() is needed after applying or removing a filter
I am using WPF DataGrid and I'm unable to edit data in it. When I double click a cell I get the error listed in the discussion name:
'Edit item' is not allowed for this view.
How can I overcome this ?
Thanks
Edit:
There are two data in my students' name and what they want to say, both of string. Then, I'm binding with my entityframework.
Below is my selectionchanged function
private void ClassDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selectedStudent = (Class)e.AddedItems[0];
var sayingCollection = selectedStudent.;
sayingCollection.AssociationChanged += ColumnsCollection_Changed;
var sayingViewSource = ((CollectionViewSource)(this.FindResource("StudentsSayingViewSource")));
sayingViewSource.Source = sayingCollection.Where(c => c.Saying.Contains(":"));
}
Let You confirm us whether you bound a Collection Item such as either IList , ObservableCollection or IEnumerable in the ItemSource.
Because the IEnumerable object doesn't have an add\remove property. So You couldn't modify the collection.
I need to flush my datagrid everytime when a treeviewitem is clicked. My code is given below.
private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
this.dataGrid1.Columns.Clear();
this.dataGrid1.ItemsSource= null;
String path =this.treeView1.SelectedItem;
if (!File.Exists(path))
MessageBox.Show("Not Found");
else
{
ob.provider(path);
// String data = #"C:\logs.xml";
string data = path;
objref.functionality(data);
this.dataGrid1.ItemsSource = objref.Result;
}
}
But everytime when I click a treeview item datagrid is not cleared-- it's appended with incoming data.
I used both dataGrid1.Columns.Clear() and dataGrid.ItemSource= null;
How can i do this??
If you are populating the DataGrid by using:
dataGrid.Items.Add(someObject);
Then you should be able to use:
dataGrid.Items.Clear();
To remove all the rows.
If you are binding to the ItemsSource like:
dataGrid.ItemsSource = someCollection;
Then you should be able to set the ItemsSource to null and it will remove all the rows.
EDIT:
Don't forget to refresh it:
dataGrid.Items.Refresh();
You may consider using ObservableCollection<> class rather than IEnumerable<>.
ObservableCollection<User> users = new ObservableCollection<User>();
dataGrid1.ItemsSource = users;
You can clear the datagrid by using the below code.
users.Clear();
I have tried several approaches and this was by far the best and most reliable one:
dataGrid.Columns.Clear();
dataGrid.Items.Clear();
dataGrid.Items.Refresh();
I had a public IEnumerable collection which is appended every time the function is called. So by overwriting it, I flushed the Data in my Datagrid.
I was able to clear my Data-Grid by setting the DataContext to null.
DataGrid.DataContext=null;
If it is bound an Itemsource, the simplest way is
dataGrid1.ItemSource = null;
Can I not remove items from a databound listview?
I bind the list view to a collection of users. lets say the listview is displaying name/address from the test object. If I try to remove the first item as below, it still displays all the records in the collection. This does not serve any good purpose. I just want to know what am I missing.
I'm suspecting it is because the datasource is still pointing to the collection which is unchanged. but if I manually change the listview items, shouldn't it take precedence?
protected void Page_Load(object sender, EventArgs e)
{
lvTest.DataSource = new List<TestObj>{ obj1, obj2..}; //pseudo code
lvTest.DataBind();
lvTest.Items.RemoveAt(0);
}
UPDATE
I understand this is not a good way of doing this. But the purpose of this question is to know why this does not work.
I think this might be a bug in the listview control. If you check the items count in the debugger after the first item is removed, you can see that the actual count is reduced by 1, but it still renders it.
Also, if you did lvTest.Items[0].Visible = false; after the RemoveAt(0), it actually makes the second item invisible which means that listview considers the first item removed but renders it regardless.
Update 2
On request, markup and codebehind used for test are below.
<asp:ListView ID="lvTest" runat="server" >
<LayoutTemplate><asp:PlaceHolder ID="itemPlaceholder" runat="server" /></LayoutTemplate>
<ItemTemplate>
<div><%# Eval("CompanyName")%><hr /></div>
</ItemTemplate>
<EmptyDataTemplate><div>None</div></EmptyDataTemplate>
</asp:ListView>
protected void Page_Load(object sender, EventArgs e)
{
lvTest.DataSource = GetCompanyList();
lvTest.DataBind();
lvTest.Items.RemoveAt(0);
}
public static List<Company> GetCompanyList()
{
List<Company> c = new List<Company>();
Company c1 = new Company();
c1.CustomerID = "2122";
c1.ContactName = "testc1";
c1.CompanyName = "test2";
Company c2 = new Company();
c2.CustomerID = "2123";
c2.ContactName = "testc2";
c2.CompanyName = "test2";
c.Add(c1);
c.Add(c2);
return c;
}
Yes you should be able to. As I understand it, the databinding is purely a process to populate the entries on the listview, so removing them after should work.
However, if this is what you want to do, a databound list does not seem like the right answer. Either get the data first, modify it, and populate the listview with the amended list; or amend the datastream to reflect jsut what you need - which you say is not an option.
What you are saying is that you want it to be databound, but you don't have a data source that actually matches the list you require. This means it should not be databound.
Another possibility that might be interesting is to use javascript/jquery to remove the items, which migh indicate whether this is a rendering problem or an object problem.
You may have to rebind the list with:
lvTest.DataBind();
Just for kicks, try binding the ListView only on the first page load.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
lvTest.DataSource = new List<TestObj>{ obj1, obj2 ..};
lvTest.DataBind();
}
lvTest.Items.RemoveAt(0);
}
Have you tried removing it from the datasource?
List<TestObj> l = lvTest.DataSource;
l.RemoveAt(0);
I don't think you can remove the items directly from the listview - they have to be removed from the bound datasource.
Another way to populate the listbox is with a loop and add it to the items:
List<string> l = new List<string>{"A", "B", "C"};
//this.listBox1.DataSource = l;
foreach (string s in l)
{
this.listBox1.Items.Add(s);
}
You should be able to use the RemoveAt now with it.
List data = new List<TestObj>{ obj1, obj2..}; //pseudo code
lvTest.DataSource = data;
lvTest.DataBind();
// if you want to remove, remove from data source and rebind
data.RemoveAt(0)
lvTest.DataSource =data;
lvTest.DataBind();
if you remove item from list view it will remove item from list view item collection but you already data blinded to list view with fist items, until you rebind, those items will display in the list view.
But when rebinding what is happening is it take data from data source not from list view items. again it will rebind fist items because list view remove not doing any change on data source.
best way is update the data source and rebind it.
I've had problems with this type of thing. Give this a try (VB but you get it)
for i as int = lvTest.Items.count -1 to 0
lvTest.Items.RemoveAt(i)
Next
There seems to be problems when the items in the list have to "reposition" themselves.