I want to print a receipt in wpf with out using report viewer or crystal report. I want to use only print dialog box in wpf.
Here's a snippet of code showing very simple usage of crystal. This has a reportviewer involved, but that is optional as I explained in comments.
ReportDocument rpt = new CrystalReport1();
Person person = new Person
{
JobTitle="Director",
Gender="M",
HireDate = new DateTime(2015,1,1)
};
List<Person> OnePerson = new List<Person>();
OnePerson.Add(person);
rpt.SetDataSource(OnePerson);
crystalReportViewer1.ReportSource = rpt;
crystalReportViewer1.Refresh();
Here CrystalReport1 is in my solution like any class or window and I've designed it there.
That can be built against any table stored procedure view or class. If you work vs a database then you could use odbc to read from there but this is rarely a good idea and you're best getting the data externally.
So long as you present data to the report which has the same fields with matching types in it then it'll take a List even if you design against a database. This means you can easy set up a dummy table with data in it and prototype quickly. Then later switch over to an entirely different source.
Related
I know this question has been asked and discussed a lot (e.g. Here and Here and this Article). Nevertheless, i still feel confused about it. I know that DbContexts should not live for the duration of application lifetime, i know they should be used per Form (window) or per Presenter. The problem is that i don't have Forms or Presenters. I have a single Form (Window) with many view models, some of them which live for the duration of the application and almost all of my view models depend on DbContext (LOB application, WPF, MVVM, Sql Server CE).
My solution is to hide DbContext behind a factory which is injected in all view models that need access to DbContext and those view models create/dispose of the DbContext when their corresponding view is loaded/unloaded.
I would like to know if this solution has any problems or if there is a better solution you could advise ?
I tend to lay my projects out as follows;
1) Presentation Layer:
Contains my Views and ViewModels
2) Business Layer:
Contains my business logic
3) Data Layer:
Contains my models
My Presentation layer calls into the business layer to populate local copies (held in the ViewModel) of the data I wish to use in my ViewModel / View.
This is achieved with a Using statement, something like;
Using DBContext As Entities = ConnectToDatabase()
Dim clsApprovalTypes As New Repositories.clsApprovalTypesRepository(DBContext)
dbResults = clsApprovalTypes.GetRecords()
End Using
Return dbResults
Here I simply pass in the Context into Repository, once the data has been returned, the "End Using" will dispose of my context.
To update the context with changes made in my ViewModel / View, I use an AddEdit routine, which accepts a record, and updates / Adds to the context as necessary, using a similar methodology to the above, something like;
Using DBContext As CriticalPathEntities = ConnectToDatabase()
Dim clsApprovalTypes As New Repositories.clsApprovalTypesRepository(DBContext)
clsApprovalTypes.AddEditRecord(ApprovalTypeToSave)
Try
clsApprovalTypes.SaveData()
Catch ex As Exception
Return ex
End Try
End Using
Where my AddEdit routine is something like;
SavedRecord = New ApprovalType 'Store the Saved Record for use later
Dim query = From c In DBContext.ApprovalTypes
Where c.ApprovalType_ID = RecordToSave.ApprovalType_ID
Select c
If query.Count > 0 Then
SavedRecord = query.FirstOrDefault
End If
'
' Use Reflection here to copy all matching Properties between the Source Entity
' and the Entity to be Saved...
'
SavedRecord = Classes.clsHelpers.CopyProperties(RecordToSave, SavedRecord)
If query.Count = 0 Then
Try
DBContext.ApprovalTypes.Add(SavedRecord)
Catch ex As EntityException
Return ex
End Try
End If
I wrote a little more about some of this here;
https://stackoverflow.com/a/15014599/1305169
I would like to stick with one single form and ReportViewer control, and at runtime assign various reports and data sources. The diverse and complex solutions to this revealed by a quick google check prompted me to rather ask here. How can I achieve this?
You'll need a form featuring a ReportViewer control, RDLC reports, and data sources; there are possibly several ways of implementing this, but you can have a "report manager" class exposing methods that each display a specific report (ex. ShowOrdersReport(), ShowTimeSheetReport(), etc.) - or you could define a base ReportBase class with a Show() method implementation that prompts for parameters when needed... whatever works, it will essentially boil down to this:
var reportForm = new ReportViewerForm(); // instantiate the form
// load the report definition into the viewer:
reportForm.reportViewer1.LocalReport.ReportEmbeddedResource = "Namespace.Report.rdlc";
// loading the data works great with a DataSet:
var data = _reportingDataSet.Tables[0];
// create the ReportDataSource with the report data:
var reportDataSource = new ReportDataSource("rdsReportDataSource", data);
reportForm.ShowReport(new[] { reportDataSource });
Here you'll want to inject the _reportingDataSet dependency; if you're using parameterized stored procedures, you'll want to prompt for the report parameters before you populate the DataSet.
The ShowReport() method adds the data sources to LocalReport.DataSources, and then calls RefreshReport() which displays the report you've specified.
public void ShowReport(IEnumerable<ReportDataSource> dataSources)
{
foreach (var dataSource in dataSources)
reportViewer1.LocalReport.DataSources.Add(dataSource);
reportViewer1.RefreshReport();
}
If you are using Crystal report then use this on click of load report button
CrystalReportViewer.ReportSource = ReportName
If you are using MS ReportViewer control then it needs two important steps to show the reports
Assign the report file path to the ReportViewer
Set the data source
So for example a ReportViewer control named reportViewer1 needs to display a SomeReport.rdlc file then following code is required (let's say on click of a button)
this.reportViewer1.LocalReport.ReportPath = #"Add absolute path of rdlc file"//e.g. #"C:\SomeReport.rdlc" ;
this.reportViewer1.RefreshReport();
This is just a simple example and for simplicity i have used static report if you need to display data from database just assign datasource property before call to RefreshReport
e.g.
this.reportViewer1.LocalReport.DataSources.Add(MyreportDataSource);
where MyreportDataSource is object of type ReportDataSource, you can easily convert any ADO.net DataTable to ReportDataSource object.
I hope this much info will do for you, in case you want to see more details you may refer a very good article at this location
http://www.c-sharpcorner.com/UploadFile/robo60/StandaloneRDLCReports11142007183516PM/StandaloneRDLCReports.aspx
I'm using a BindingList to display a list of Person objects in a DataGridView in a Windows Forms application. Changes to the DataGridView change the underlying BindingList. I've got this part working.
Now I want the list persisted to a database table. Reading the list from the database and populating the Person list is straight forward, but if I add/edit/delete a person from the DataGridView, how and when do I persist that change back to the database?
(Secondly, is this approach okay or am I missing some bigger picture? I don't want to use data tables because I want to work with my code in an abstracted object oriented way.)
For easy persistence of objects in Windows Forms for a start you can use LINQ2SQL, it does exactly what you want plus also materializes objects when you want to gather them from database.
Quick example, after you create linq context from database schema for supported databases, which is SQL Server (Express), all you need is to create it's instance in your form and use it during single atomic operation with data - read, edit, write or cancel.
private YourAppContext context;
private void RenewContext()
{
context = new YourAppContext();
}
private void LoadData()
{
RenewContext();
DataGridView1.DataSource = context.Articles.OrderByDescending(x => x.DatePosted).Take(10);
}
private void AcceptButtonPressed()
{
context.SubmitChanges();
}
private void CancelButtonPressed()
{
LoadData();
}
Obviously you can pass your data through BindingSource.
Time and again I find myself creating a database utility class which has multiple functions which all do almost the same thing but treat the result set slightly differently.
For example, consider a Java class which has many functions which all look like this:
public void doSomeDatabaseOperation() {
Connection con = DriverManager.getConnection("jdbc:mydriver", "user", "pass");
try {
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT whatever FROM table"); // query will be different each time
while (rs.next()) {
// handle result set - differently each time
}
} catch (Exception e) {
// handle
} finally {
con.close();
}
}
Now imagine a class with 20 of these functions.
As you can see, tons of boilerplate (opening a connection, try-finally block), and the only thing that changes would be the query and the way you handle the result set. This type of code occurs in many languages (considering you're not using an ORM).
How do you manage your DB utility classes so as to reduce code duplication? What does a typical DB utility class look like in your language/framework?
The way I have done in one of my project is that I followed what Spring does with JDBC template and came up with a Query framework. Basically create a common class which can take select statement or pl/sql calls and bind parameters. If the query returns resultset, also pass the Rowmapper. This rowmapper object will be called by the framework to convert each row into an object of any kind.
Example -
Query execute = new Query("{any select or pl/sql}",
// Inputs and Outputs are for bind variables.
new SQL.Inputs(Integer.class, ...),
// Outputs is only meaningful for PL/SQL since the
// ResultSetMetaData should be used to obtain queried columns.
new SQL.Outputs(String.class));
If you want the rowmapper -
Query execute = new Query("{any select or pl/sql}",
// Inputs and Outputs are for bind variables.
new SQL.Inputs(Integer.class, ...),
// Outputs is only meaningful for PL/SQL since the
// ResultSetMetaData should be used to obtain queried columns.
new SQL.Outputs(String.class), new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Actor actor = new Actor();
actor.setFirstName(rs.getString("first_name"));
actor.setSurname(rs.getString("surname"));
return actor;
});
Finally a Row class is the output which will have list of objects if you have passed the RowMapper -
for (Row r : execute.query(conn, id)) {
// Handle the rows
}
You can go fancy and use Templates so that type safety is guaranteed.
Sounds like you could make use of a Template Method pattern here. That would allow you to define the common steps (and default implementations of them, where applicable) that all subclasses will take to perform the action. Then subclasses need only override the steps which differ: SQL query, DB-field-to-object-field mapping, etc.
When using .net, the Data Access Application Block is in fairly widespread use to provide support for the following:
The [data access] application block
was designed to achieve the following
goals:
Encapsulate the logic used to perform
the most common data access tasks.
Eliminate common coding errors, such
as failing to close connections.
Relieve developers of the need to
write duplicated code for common data
access tasks.
Reduce the need for
custom code.
Incorporate best
practices for data access, as
described in the .NET Data Access
Architecture Guide.
Ensure that, as
far as possible, the application block
functions work with different types of
databases.
Ensure that applications
written for one type of database are,
in terms of data access, the same as
applications written for another type
of database.
There are plenty of examples and tutorials of usage too: a google search will find msdn.microsoft, 4guysfromrolla.com, codersource.com and others.
I have a problem with Linq and ObservableCollections in my WPF application.
Context of the problem:
I've created a very simple SQL database with two tables: User and BankAccounts.
The User Table has an one-to-many relationship with the BankAccounts Table. Next I've created Linq-to-SQL dataclasses, which worked fine ==> the assosiation between the two tables was detected as well.
Next I've created a function to retreive all Users which works fine:
DataClassesDataContext dc = new DataClassesDataContext
var query = from u in dc.Users
select u;
Now suppose I want to add a new BankAccount to each user (not very likely but still).
I could add the following code
for each(User u in query)
{
u.BankAccounts.Add(New BankAccount());
}
The above works all fine. The BankAccounts property is automaticly part of the User class, due to the assosiation in the database and Linq DataClasses.
However, in my application I first add the query results to an ObservableCollection. Hereby I could use all sorts off databinding and changenotification. This is accomplished by the following code;
ObservableCollection<User> oUsers = new ObservableCollection<User>(query);
Problem: Within the ObservableCollection I can't do anyting with the users BankAccounts property because it is now of type EntitySet<>. So I can't do the following statement anymore.
for each(User u in oUsers)
{
u.BankAccounts.Add(New BankAccount());
}
Somehow, when queryresults are added to an observablecollection It is not possible to acces the user.BankAccounts properties anymore. However, it is possible to bind the BankAccounts Property to any control, like a listbox, and it contains the correct data.
Does someone now how I can create an observableCollction (or similar collection) from wich I can access these "assosiated" properties? I'm realy looking forward for to a solution.
Thanks in advance!
Best regards,
Bas Zweeris
E: Bas.Zweeris#Capgemini.com
Keep track of the original query which will implement IQueryable, you can run any further queries you need against that.
The ObservableCollection should just be for WPF to have something to bind to - its very useful if you want to add a new collection item but not have it pushed to the database before the user has had chance to edit it.
eg.
// Create a new blank client type
var ct = new ClientType()
{
IsArchived = false,
Description = "<new client type>",
Code = "CT000",
CanLoginOnline = true
};
// Tell the data source to keep track of this object
db.ClientTypes.InsertOnSubmit(ct);
// Also add the object to the observable collection so that it can immediately be shown in the UI and editted without hitting the db
clienttypes.Add(ct);