I am creating a new window popup window using
PopupWindows.PaymentsSummary paymentsSummary = new PopupWindows.PaymentsSummary
paymentsSummary.ParentWindow = Window.GetWindow(this);
paymentsSummary.ShowDialog();
on my load function in the Payment summary window I have
private void Window_Loaded(object sender, RoutedEventArgs e)
{
basepage.payments.BindPaymentSummaryToDataGrid(uiActiveItems, basepage.user.terminal.TerminalId, true);
basepage.payments.BindPaymentSummaryToDataGrid(uiInActiveItems, basepage.user.terminal.TerminalId, false);
}
The function is
public void BindPaymentSummaryToDataGrid(DataGrid dgrid, int terminalId, bool isActivePayment)
{
BLPinNumber pins = new BLPinNumber();
string pinNumber = String.Empty;
long pinId = pins.getPinId(terminalId, ref pinNumber);
using (var dbEntities = new DatabaseAccess.Schema.Entities())
{
dgrid.DataContext = dbEntities.getPaymentRecordsByPinId((int)pinId, isActivePayment);
}
}
The above code calls a Stored Proc in SQL Server and returns an object,
However when the app runs I get the error when clicking to show the popup on the following line paymentsSummary.ShowDialog();
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I have worked that down to the following code in the XAML for the datagrid
DataGrid ItemsSource="{Binding}" Grid.Column="{Binding}"
If i remove this code it works but the data doesnt load obvioulsy.
So what I believe I need to do is bind the datagrid onShowDialog method.
How do i create this ?
Or is there a better way of doing this using the Entity framework, im used to ASP.NET where working with DATAGRIDS seem easier, if ablight less powerful.
Many thanks
Your problem is lazy loading!, you got 2 options:
select the data with eager loading (change the getPaymentRecordsByPinId).
do not dispose the dbEntities while popup is open.
Related
I am testing the workings of WPF with Entity Framework. I have a SS table called Vendors {VendorCode, VendorName, Phone}.
I am sticking with only EF and I am able to display and navigate the recordset on a WPF form with buttons first, next, last etc. I used the instructions on the MSDN site (Create a simple data application with WPF and Entity Framework 6)
My problem is the recordset is sorted only in the order it was entered into SS. I would like to sort it by VendorCode or by VendorName to make it easier on the user. I can't seem to make it sort the recordset or table data coming through EF.
Can you please help? Thank you!
Here is a snippet of my code:
public Vendor newVendor { get; set; }
VendorsEntities context = new VendorsEntities();
CollectionViewSource VendorViewSource;
public MainWindow()
{
InitializeComponent();
newVendor = new Vendor();
VendorViewSource = ((CollectionViewSource)
(FindResource("VendorViewSource")));
DataContext = this;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// this next line doesn't do it
context.Vendors.OrderBy(Vendor => Vendor.VendorCode);
context.Vendors.Load();
VendorViewSource.Source = context.Vendors.Local;
}
private void NextCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
VendorViewSource.View.MoveCurrentToNext();
}
You would need to set the result of OrderBy method in to some variable and then use that as OrderBy will return a new reference, or you can use the set the reference of context.Vendors to the reference returned by OrderBy() method.
Try doing it like:
var ordered = context.Vendors.OrderBy(Vendor => Vendor.VendorCode);
VendorViewSource.Source = ordered;
another way can be to order it after bringing the result back, but it is not a recommended approach, first approach should be preferred, but just giving another option which is also possible:
var vendors = context.Vendors.Load().OrderBy(Vendor => Vendor.VendorCode);
VendorViewSource.Source = vendors;
Hope it helps!
You are sorting context, not displayed items. Try:
VendorViewSource.Source = context.Vendors.OrderBy(Vendor => Vendor.VendorCode);
I've created a code first context with a DbSet property
I work with Windows form. If I bind as follow:
_context.Schedules.Load();
scheduleBindingSource.DataSource = _context.Schedules.Local.ToBindingList();
All works great and when I save as follow:
this.Validate();
scheduleBindingSource.EndEdit();
_context.SaveChanges();
The data persists; But when I bind the data like this:
var res = _context.Schedules.Where(k => k.EmployeeName.Equals(employeeComboBox.Text)).ToList();
scheduleBindingSource.DataSource = res;
When I save data doesn't persis!
I'm thinking that the ToList() method is not good, but I can't find alternative to get a BindingList connected to the Local set of data inside the context.
Thanks,
Andrea
You can try this:
_context.Schedules.Where(k => k.EmployeeName.Equals(employeeComboBox.Text)).Load();
scheduleBindingSource.DataSource = _context.Schedules.Local.ToBindingList();
That should only bring the schedules that meet the condition. When you call the Load method after the Where method, it is going to bring to memory only the records that meet the condition. Later, when you call the Local property,it will give you an ObservableCollection<Schedule> that contains all the objects that are currently tracked by the DbContext which thy are going to be the elements you loaded before. At the end, when you call the ToBindingList extension method, it will returns an BindingList<Schedule> that stays in sync with the given ObservableCollection<Schedules>.
The reason that caused the non-persistance of the data is caused by DataGridView (or the BindingSource), that don't add to context the new istance of the just added row.
So I've disabled the AllowUserToAddRow property (now I'm using BindingNavigator Add Button)
And implemented these two events as follow:
private void scheduleBindingSource_AddingNew(object sender, AddingNewEventArgs e)
{
_scheduleAdding = true;
}
private void scheduleBindingSource_CurrentChanged(object sender, EventArgs e)
{
if (_scheduleAdding)
{
Schedule s = (Schedule)scheduleBindingSource.Current;
s.EmployeeName = employeeComboBox.Text;
s.From = new DateTime(dateTimePicker1.Value.Year, dateTimePicker1.Value.Month, 1);
_context.Schedules.Add(s);
_scheduleAdding = false;
}
}
I am working in silverlight application using WCF. I want to show specific row from the database in the data grid.
I found e.result BUT this will show the whole from DB.
Below is my code:
public TrainingBatchesUsersResults(int TraineeID)//, int TrainingProgramID, int >ReadyContainerID, int TrainingBatch, int ReadyContainerItemID)
{
InitializeComponent();
XraySimulatorWCFServices.XraySimulatorServiceClient XrayClient =new XraySimulatorWCFServices.XraySimulatorServiceClient();
XrayClient.GetTrainingBatchesUsersResultsCompleted += new EventHandler<
XraySimulatorWCFServices.GetTrainingBatchesUsersResultsCompletedEventArgs>(DisplayTrainingBatchesUsersResults);
XrayClient.GetTrainingBatchesUsersResultsAsync(TraineeID);
LayoutRoot.UpdateLayout();
}
private void DisplayTrainingBatchesUsersResults(object sender, XraySimulatorWCFServices.GetTrainingBatchesUsersResultsCompletedEventArgs e)
{
dgvResult.ItemsSource = e.Result;
dgvResult.Visibility = System.Windows.Visibility.Visible;
}
Just set your ItemsSource to the single row you want to show then, rather than the whole results collection. For example dgvResult.ItemsSource=e.Result.FirstOrDefault(x=>x.Id==theIdYouWantToShow)
BUT what you really want is to do this further up the chain so that you only RETURN the single row you want, rather than return the whole table and reduce that set on the client.
Your call XrayClient.GetTrainingBatchesUsersResultsAsync(TraineeID); presumably is returning all your rows, why not have a new method that only returns the single result you're interested in?
Just so you are all aware, I have almost solved the issue BUT there is a key item in my way.
Alright. I have a "DataModule" class where there are several DataAdaptors, my DataSet, and the Connection.
My database is working fine, and so is saving and retrieving (including updating and deleting) data. If I put a TextBox on the DataModule form, and use an OleDbReader, and the following statement: txtBoxTest.Text = reader["firstName"].ToString();
Then the selected record's (which I have chosen by ID number) first name appears in the box.
However, the ACTUAL place for this data to appear is on another form, and as we know, components on a Windows Forms Application are set to "private", by default. Thus, my dilemma.
Question is below this line
How can I make the data appear in the correct form's TextBoxes (which is PatientRecord.cs) using the DataModule class' reader, and the statement of code I provided?
Many thanks!
There are Some way for Data transfer between forms.I explain one of common ways:
Sender form:
FrmChild child = new FrmChild(number,line,this.Width);
child.Owner = this;
child.Show();
Receiver form:
public partial class FrmChild : Form
{
int frmw;//A public varaible
public FrmChild()//normal constrauctor
{
InitializeComponent();
}
public FrmChild(String cNumber,byte LINE,int w)//custom constrauctor
{
frmw = w;
InitializeComponent();
}
}
Given a DataGridView that has a BindingSource set like this:
On a winform, we add a BindingSource object using the designer, called myBindingScource.
Then on the Form.Designer.cs we add this to the InitializeComponents()
myBindingSource.DataSource = typeof(MyLinq.Person); //Mylinq is the autogenerated Linq Model/Diagram
Later, in the form itself we do:
myDataView.DataSource = myBindingSource;
and then we have a method that populates the Grid…
using ( myDataContext mdc = new MyDataContext() )
{
myDataView.DataSource = from per in mdc.person
select per;
}
As an aside note, I've set up the columns in Design Time, and everything shows ok.
Since the LINQ 2 SQL is not returning an Anonymous, the "myDataView" is editable, and here comes the question…
Question is: how do I persist those changes?
There are dozens of events in the datagrid, and I'm not sure which one is more appropriate. Even if I try one of the events, I still don't know what is the code I need to execute to send those changes back to the DB in order to persist the changes.
I remember back in the ADO.NET DataSet days, you would do dataadapter.Update(dataset);
Also imagine that both the retrieve and the persist() are on a Business Layer and the method signature looks like this:
public void LoadMyDataGrid(DataGridView grid);
that method takes the form's grid and populates it using the LINQ2SQL query shown above.
Now I'd like to create a method like this:
public void SaveMyDataGrid(DataGridView grid); // or similar
The idea is that this method is not on the same class (form), many examples tend to assume that everything is together.
RowValidated event would be a good place to check to see if it's time to persist changes to the database.
this.dataGridView1.RowValidated += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_RowValidated);
private void dataGridView1_RowValidated(object sender, DataGridViewCellEventArgs e)
{
MyLinq.Person person = dataGridView1.Rows[e.RowIndex].DataBoundItem as MyLinq.Person;
if (person != null)
{
// save this person back to data access layer
}
}
After your edit:
I wouldn't pass back a datagrid instance to your service layer. I'd pass back IEnumerable<MyLinq.Person> or IList<MyLinq.Person> then iterate over the collection in your service layer, and depending on the logic performed; persist the changes to the data access layer (your database)
The 'save' method on the DataContext object is SubmitChanges().
using (MyContext c = new MyContext())
{
var q = (from p in c.People
where p.Id == 1
select p).First();
q.FirstName = "Mark";
c.SubmitChanges();
}
As Michael G mentioned, you'll need to gather the changes, and pass them back to the bll object.