Jaime Bula
Top achievements
Rank 2
Jaime Bula
asked on 27 Aug 2012, 10:40 PM
Hi,
I've been looking everywhere, but I don't find any "Import Designer Generated Report to App Guidance".
Should they be saved on the Database or DLL?, How to set the Data Source?, Best Practices? Security?? Etc...
This info will be appreciatted.
I've been looking everywhere, but I don't find any "Import Designer Generated Report to App Guidance".
Should they be saved on the Database or DLL?, How to set the Data Source?, Best Practices? Security?? Etc...
This info will be appreciatted.
2 Answers, 1 is accepted
0
Accepted
erwin
Top achievements
Rank 1
Veteran
Iron
answered on 28 Aug 2012, 04:11 PM
Hi Jaime
Working on the same questions, this is what I came up so far:
Using .trdx files directly in my App for simplicity (because I want Power Users to be able to design and use their own Reports):
ReportDefinitionFile contains the path to the .trdx file. But you can store the report definition XML wherever you want. See the overloads to the Deserialize method.
Not sure about subreports that are somewhere else than in files yet - you would probably have to implement your own ReportResolver.
If you want to use .dlls there is no point in using the standalone designer use the Visual Studio Integrated Designer.
I'm learning on this - so I don't know it this is best practice, but seems to work ;-)
Fill In Report Parameters:
Define standard Names for Parameters where your Reports expect Values or preset List of possible Values from your Application:
The sample shows how to fill multi value parameters. Note that I set the Visible Attribute to false for Parameters that the User should not see (In the designer you have to set this to true to be able to fill in Values for Preview).
I support two methods of dynamically changing the ConnectionString of the DataSources:
If the report defines a Parameter called "OctopusConnectionString", I just fill that in. The report uses Binding (see old forum posts on examples) to set the DataSource.ConnectionString property from a Report Parameter.
This allows the Report to use additional DataSources with other Connection Strings.
If the report does not define a Parameter called "OctopusConnectionString", I set the Report.DataSource.ConnectionString property to my apps connection string.
As other DataItems in the Report have their own DataSources, I have to recursively change the Connection String there too. This is where it gets a bit clumsy, see my other posts:
Maybe someone at Telerik comes up with a more elegant solution to this.
Regards
Erwin
Working on the same questions, this is what I came up so far:
Using .trdx files directly in my App for simplicity (because I want Power Users to be able to design and use their own Reports):
ReportDefinitionFile contains the path to the .trdx file. But you can store the report definition XML wherever you want. See the overloads to the Deserialize method.
Not sure about subreports that are somewhere else than in files yet - you would probably have to implement your own ReportResolver.
If you want to use .dlls there is no point in using the standalone designer use the Visual Studio Integrated Designer.
I'm learning on this - so I don't know it this is best practice, but seems to work ;-)
// use the telerik ReportXmlSerializer to create a Report object from XML
var xmlSerializer =
new
ReportXmlSerializer();
var reportDocument = (Telerik.Reporting.Report)xmlSerializer.Deserialize(ReportDefinitionFile);
// create a ReportSource object
var reportSource =
new
InstanceReportSource();
reportSource.ReportDocument = reportDocument;
// get the applications connection string (I'm using LLBLGEN here)
SqlConnectionStringBuilder scsb =
new
SqlConnectionStringBuilder();
scsb.ConnectionString = CommonDaoBase.ActualConnectionString;
// ... needed by other parts ot the app
this
.connectionString = CommonDaoBase.ActualConnectionString;
this
.databaseDatabase = scsb.InitialCatalog;
this
.databaseServer = scsb.DataSource;
this
.databaseLogin = scsb.UserID;
this
.databasePassword = scsb.Password;
this
.integratedSecurity = scsb.IntegratedSecurity;
// fill in well-known Report Parameters if the report defines them
// if ReportParameter "OctopusConnectionString" is present, the report uses Binding to set up it's DataSource objects
if
(!SetReportParameters(reportDocument))
{
// no OctopusConnectionString Parameters, set the ConnectionString on the Report DataSource
SqlDataSource sds = (SqlDataSource)reportDocument.DataSource;
sds.ConnectionString = scsb.ConnectionString;
// try to patch DataItems in the report (Table, Crosstab, List, Subreports have their own DataSource objects)
SetConnectionStrings(reportDocument.Items, scsb.ConnectionString);
}
this
.reportViewer1.ReportSource = reportSource;
this
.reportViewer1.RefreshReport();
Fill In Report Parameters:
Define standard Names for Parameters where your Reports expect Values or preset List of possible Values from your Application:
The sample shows how to fill multi value parameters. Note that I set the Visible Attribute to false for Parameters that the User should not see (In the designer you have to set this to true to be able to fill in Values for Preview).
I support two methods of dynamically changing the ConnectionString of the DataSources:
If the report defines a Parameter called "OctopusConnectionString", I just fill that in. The report uses Binding (see old forum posts on examples) to set the DataSource.ConnectionString property from a Report Parameter.
This allows the Report to use additional DataSources with other Connection Strings.
private
bool
SetReportParameters(IReportDocument src)
{
bool
connectionStringParameterDefined =
false
;
foreach
(ReportParameter p
in
src.ReportParameters)
{
if
(p.Name ==
"OctopusOrganizations"
)
{
DataTable dt =
new
DataTable();
dt.Columns.Add(
"Label"
,
typeof
(
string
));
dt.Columns.Add(
"Value"
,
typeof
(
long
));
System.Collections.Generic.List<
long
> allValues =
new
System.Collections.Generic.List<
long
>();
OrganizationCollection oc =
new
OrganizationCollection();
oc.GetMulti(
null
);
foreach
(OrganizationEntity org
in
oc)
{
DataRow r = dt.NewRow();
r[
"Label"
] = org.Name;
r[
"Value"
] = org.Id;
allValues.Add(org.Id);
dt.Rows.Add(r);
}
p.Text =
"Organizations"
;
p.AvailableValues.ValueMember =
"Value"
;
p.AvailableValues.DisplayMember =
"Label"
;
p.AvailableValues.DataSource = dt;
p.MultiValue =
true
;
if
(Globals.ApplicationGlobals.ApplicationSettings.ReportAllOrganizations)
{
p.Visible =
false
;
p.Value = allValues;
}
else
{
p.Visible =
true
;
}
}
else
if
(p.Name ==
"OctopusSoftwareCategories"
)
{
DataTable dt =
new
DataTable();
dt.Columns.Add(
"Label"
,
typeof
(
string
));
dt.Columns.Add(
"Value"
,
typeof
(
long
));
System.Collections.Generic.List<
long
> allValues =
new
System.Collections.Generic.List<
long
>();
SoftwareCategoryCollection scc =
new
SoftwareCategoryCollection();
scc.GetMulti(
null
);
foreach
(SoftwareCategoryEntity sc
in
scc)
{
DataRow r = dt.NewRow();
r[
"Label"
] = sc.Name;
r[
"Value"
] = sc.Id;
allValues.Add(sc.Id);
dt.Rows.Add(r);
}
p.Text =
"Software Categories"
;
p.AvailableValues.ValueMember =
"Value"
;
p.AvailableValues.DisplayMember =
"Label"
;
p.AvailableValues.DataSource = dt;
p.MultiValue =
true
;
if
(Globals.ApplicationGlobals.ApplicationSettings.ReportAllSoftwareCategories)
{
p.Visible =
false
;
p.Value = allValues;
}
else
{
p.Visible =
true
;
}
}
else
if
(p.Name ==
"OctopusSoftwarePackages"
)
{
DataTable dt =
new
DataTable();
dt.Columns.Add(
"Label"
,
typeof
(
string
));
dt.Columns.Add(
"Value"
,
typeof
(
long
));
System.Collections.Generic.List<
long
> allValues =
new
System.Collections.Generic.List<
long
>();
SoftwarePackageCollection spc =
new
SoftwarePackageCollection();
PredicateExpression filter =
null
;
filter =
new
PredicateExpression();
filter.Add(
new
FieldCompareValuePredicate(EntityFieldFactory.Create(SoftwareCategoryFieldIndex.Junk), ComparisonOperator.Equal, 0));
RelationCollection relations =
new
RelationCollection();
relations.Add(SoftwarePackageEntity.Relations.SoftwareCategoryEntityUsingSoftwareCategoryId);
spc.GetMulti(filter, relations);
foreach
(SoftwarePackageEntity sp
in
spc)
{
DataRow r = dt.NewRow();
r[
"Label"
] = sp.Name;
r[
"Value"
] = sp.Id;
allValues.Add(sp.Id);
dt.Rows.Add(r);
}
p.Text =
"Software Packages"
;
p.AvailableValues.ValueMember =
"Value"
;
p.AvailableValues.DisplayMember =
"Label"
;
p.AvailableValues.DataSource = dt;
p.MultiValue =
true
;
if
(Globals.ApplicationGlobals.ApplicationSettings.ReportAllSoftwareCategories)
{
p.Visible =
false
;
p.Value = allValues;
}
else
{
p.Visible =
true
;
}
}
else
if
(p.Name ==
"OctopusReportName"
)
{
p.Value =
"Octopus "
+
this
.ReportName;
p.Visible =
false
;
}
else
if
(p.Name ==
"OctopusDatabase"
)
{
p.Value =
this
.Database;
p.Visible =
false
;
}
else
if
(p.Name ==
"OctopusLicensee"
)
{
p.Value =
this
.LicenseeName;
p.Visible =
false
;
}
else
if
(p.Name ==
"OctopusReportFile"
)
{
p.Value =
this
.ReportDefinitionFile;
p.Visible =
false
;
}
else
if
(p.Name ==
"OctopusObjectId"
)
{
p.Value =
this
.ObjectId;
p.Visible =
false
;
}
else
if
(p.Name ==
"OctopusRevision"
)
{
p.Value = Octopus.Base.Licensing.OctopusVersion.BuildVersion;
p.Visible =
false
;
}
else
if
(p.Name ==
"OctopusVersion"
)
{
p.Value = Octopus.Base.Licensing.OctopusVersion.DisplayVersion;
p.Visible =
false
;
}
else
if
(p.Name ==
"OctopusConnectionString"
)
{
p.Value =
this
.connectionString;
p.Visible =
false
;
connectionStringParameterDefined =
true
;
}
}
return
connectionStringParameterDefined;
}
If the report does not define a Parameter called "OctopusConnectionString", I set the Report.DataSource.ConnectionString property to my apps connection string.
As other DataItems in the Report have their own DataSources, I have to recursively change the Connection String there too. This is where it gets a bit clumsy, see my other posts:
/// <summary>
/// Recursively set the connection string on all report items that have a sql datasource
/// </summary>
/// <param name="items"></param>
/// <param name="connectionString"></param>
private
void
SetConnectionStrings(Telerik.Reporting.ReportItemBase.ItemCollection items,
string
connectionString)
{
foreach
(Telerik.Reporting.ReportItemBase ib
in
items)
{
if
(ib.Items !=
null
)
{
if
(ib.Items.Count > 0)
{
SetConnectionStrings(ib.Items, connectionString);
}
}
SqlDataSource ds =
null
;
if
(ib
is
Telerik.Reporting.Chart)
{
Telerik.Reporting.Chart chart = ib
as
Telerik.Reporting.Chart;
ds = chart.DataSource
as
SqlDataSource;
}
else
if
(ib
is
Telerik.Reporting.Crosstab)
{
Telerik.Reporting.Crosstab crosstab = ib
as
Telerik.Reporting.Crosstab;
ds = crosstab.DataSource
as
SqlDataSource;
}
else
if
(ib
is
Telerik.Reporting.Table)
{
Telerik.Reporting.Table table = ib
as
Telerik.Reporting.Table;
ds = table.DataSource
as
SqlDataSource;
}
else
if
(ib
is
Telerik.Reporting.List)
{
Telerik.Reporting.List list = ib
as
Telerik.Reporting.List;
ds = list.DataSource
as
SqlDataSource;
}
else
if
(ib
is
Telerik.Reporting.SubReport)
{
Telerik.Reporting.SubReport rpt = ib
as
Telerik.Reporting.SubReport;
ds = rpt.Report.DataSource
as
SqlDataSource;
}
if
(ds !=
null
)
{
ds.ConnectionString = connectionString;
}
}
}
Maybe someone at Telerik comes up with a more elegant solution to this.
Regards
Erwin
0
Jaime Bula
Top achievements
Rank 2
answered on 28 Aug 2012, 06:57 PM
Thanx for your post!
Has pointed me on a direction. Now I'll try to make it work with the Silverlight Report Viewer.
Best Regards!
Has pointed me on a direction. Now I'll try to make it work with the Silverlight Report Viewer.
Best Regards!