This is a migrated thread and some comments may be shown as answers.

Questions/Comments on Reporting Styles

4 Answers 328 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Scott R
Top achievements
Rank 1
Scott R asked on 02 Oct 2008, 10:11 PM
So far I've been formatting reports by simply modifying the Style property of the various elements. However, I now have a situation where I would like for users to be able to override the default style. Actually, users are very unlikely to modify the styles themselves, but we need to be able to customize the styles for them.

This "report" is currently done with HTML and we use CSS to make customizations. I'm hoping we can achieve something similar with Telerik reports.

First off, is there a way to feed XML representing an "external stylesheet" directly to the report? Or do we need to write the XML to a file then set a path to that file? The XML will be stored in a database and it would be nice if we could feed the XML directly to the report without having to create a temporary file. I see that there is an overload on the ExternalStyleSheet constructor that takes a Stream. I'll see if I can get that to work.

Second, I don't see a Style Selector that is analogous to the "#ControlId" CSS selector. Is it possible to create styles in the external style sheet that target a specific control by name? If not, I guess I can work around this by setting the StyleName to always match the control name?

Third, when I try to override a style that is defined in the report with a different value in the external style sheet, it doesn't appear to work. For example, the report defines a "InfoPanel" style with a solid border. If I try to remove the border in the external style sheet the border is still there. Here is the external style sheet XML:

<?xml version="1.0" encoding="utf-8"?> 
<StyleSheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  <StyleRule> 
    <Style> 
      <BorderStyle> 
        <Default>None</Default> 
      </BorderStyle> 
    </Style> 
    <Selectors> 
      <StyleSelector> 
        <Type>ReportItemBase</Type> 
        <StyleName>InfoPanel</StyleName> 
      </StyleSelector> 
    </Selectors> 
  </StyleRule> 
</StyleSheet> 

Interestingly, setting the border style to "Dashed" instead of "None" does work (the border becomes dashed). But I seem to be unable to remove the border using "None".

I think that's it for now.

Scott

4 Answers, 1 is accepted

Sort by
0
Rossen Hristov
Telerik team
answered on 03 Oct 2008, 11:41 AM
Hello Scott R,

ExternalStyleSheet from a Stream

You can construct a new ExternalStyleSheet object by passing in a stream to one of its constructors. You can then add it to the ExternalStyleSheets collection of the Report. One place you can do this is after the InitializeComponent method call in the report's constructor:

this.ExternalStyleSheets.Add(new ExternalStyleSheet(<<your stream>>));

Targeting an item by its Name with an AttributeSelector

Report items are identified by their Name, so if you set the Name of an item, for example "txtSales" you can then use an AttributeSelector to select that item by its property Name. This is the proper way of targeting items by their Name. If you want to use such a selector in an external style sheet file, the easiest way to create it is to use design-time to define it in Report.StyleSheet and then use the Export button to export it to XML. This will save you some time.

Style Inhertance and Overriding

The issue with the border is somewhat more complex. I will do my best to explain how things work.

While in design-time, the designer decides whether to serialize each property (Style.BorderStyle.Default in you case) in the code-behind file or not. The decision is based on whether its effective current value is different from the default one.

Imagine a report with no style sheets whatsoever. If you set a BorderStyle to None that will not be serialized in the code-behind since None is the default value for BorderStyle.

Now imagine you define a global style ruling that all borders should be Solid. If you go to the property grid you will notice that the border of your item indicates that it is Solid (in a non-bold font since it is inherited from above). That is because it has inherited this from the global style and the current effective value is Solid. If you now set it to None its value will be serialized since None is different from Solid.

However, if the global style (taken from the external style sheet file) is not present/applied in design-time (which I understand will be the case in you application, i.e. you will load it at runtime from a stream) the item has no way of knowing that in the future a Solid border will come in from a global style, so it will not serialize the None value. Therefore the only way to force your item to disobey the global style coming in later is to programmatically set its border. Setting a value explicitly (inline in CSS terms) will take precedence over any parent or global settings. Thus the None will override the Solid. I know that all of this sounds too complicated, but it is the way style inheritance works in Telerik Reporting. You can take a look at the Style Inheritance and Overriding topic and all the other topics under the same category in our documentation.

Since a picture is sometimes worth more than a thousand words, I have prepared a little sample demonstrating all the issues I have tried to explain above. You can examine it carefully to see my implementation and if you have any other questions or you face difficulties with your project, I would be glad to help.
Greetings,
Ross
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Scott R
Top achievements
Rank 1
answered on 03 Oct 2008, 04:11 PM

Thank you very much for your thorough answer.

Regarding Style Inheritance and Overriding, I think you have my situation backwards (if I read your comments correctly). In my case, the border IS defined as solid at design-time. I am trying to change it to "None" using the external style sheet.

To clarify, I have created a global style for "InfoPanel" at design-time that defines a solid border. I want to remove the border using an external style sheet.

I decided to try to get around any problems related to serialized properties in the code-behind by removing all styles from the report at design-time and using external style sheets exclusively. Here's the constructor code for the report:

        public Invoice()  
        {  
            /// <summary>  
            /// Required for telerik Reporting designer support  
            /// </summary>  
            InitializeComponent();  
 
            ExternalStyleSheets.Add(new ExternalStyleSheet("~/StyleSheets/DefaultInvoiceStyleSheet.xml"));  
        }  
 
        public Invoice(string Styles)  
            : this()  
        {  
            if (!string.IsNullOrEmpty(Styles))  
                using (System.IO.Stream s = new System.IO.MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(Styles)))  
                    ExternalStyleSheets.Add(new ExternalStyleSheet(s));  
        } 

I set the InfoPanel border to "Solid" in DefaultInvoiceStyleSheet.xml like so:

<?xml version="1.0" encoding="utf-8"?>  
<StyleSheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
  <StyleRule> 
    <Style> 
      <BorderStyle> 
        <Default>Solid</Default> 
      </BorderStyle> 
    </Style> 
    <Selectors> 
      <StyleSelector> 
        <Type>ReportItemBase</Type> 
        <StyleName>InfoPanel</StyleName> 
      </StyleSelector> 
    </Selectors> 
  </StyleRule> 
</StyleSheet> 

If there are custom styles for the report (from the database) then I call the overloaded constructor. For my testing I am passing in a string with the border set to "None" like so:

<?xml version="1.0" encoding="utf-8"?>  
<StyleSheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
  <StyleRule> 
    <Style> 
      <BorderStyle> 
        <Default>None</Default> 
      </BorderStyle> 
    </Style> 
    <Selectors> 
      <StyleSelector> 
        <Type>ReportItemBase</Type> 
        <StyleName>InfoPanel</StyleName> 
      </StyleSelector> 
    </Selectors> 
  </StyleRule> 
</StyleSheet> 

This doesn't work because there is still a border on the report.

Incidentally, if I pass in a string of XML to the constructor that sets the border to "Dashed" instead of "None" then the border on the report becomes dashed. So I know that the override *can* work the way I'm doing it, it just doesn't work for "None".
0
Rossen Hristov
Telerik team
answered on 03 Oct 2008, 04:48 PM
Hello Scott R,

What you are describing is the expected behavior. If you consult the article Style Inheritance and Overriding you will see that inline style is stronger than parent and global styles:

Now, you mentioned that if you use Dashed in the XML it is working and if you use None it is not. That is very very weird. Can you please send us the exact XML that you are using and exact report definition. We would like to take a closer look at them since it should not work in both cases, i.e. the in-line Solid is stronger than anything else -- be it None or Dashed or something else.

We have reworked the previous sample and attached it again. It demonstrates how the Solid stays Solid no matter what the global style tells it. Please examine it carefully and run it with the XML that we have provided and tell us what happens. To make the report find the supplied XML file add them both to a project and set the CopyToOuputDirectory of the XML file to "Copy Always". Please, do not modify anything else before running it.

We are looking forward to the results. (and your sample report demonstrating the wrong behavior along with the your XML file).

Regards,
Ross
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Scott R
Top achievements
Rank 1
answered on 03 Oct 2008, 05:07 PM
Hi Ross,

I understand the style precedence rules. However, there are no inline styles in my report. There are only global styles. I'm trying to override the global style that defines a solid border by specifying a global style in the external style sheet that defines no border. My previous post shows the exact XML I am using to try to accomplish that.

I think I have finally found a workable solution. I changed my report constructor like this:

        public Invoice(string Styles)  
            : this()  
        {  
            if (!string.IsNullOrEmpty(Styles))  
            {  
                ExternalStyleSheets.Clear();  
                using (System.IO.Stream s = new System.IO.MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(Styles)))  
                    ExternalStyleSheets.Add(new ExternalStyleSheet(s));  
            }  
        } 

By clearing the "default" external style sheet first, then loading the custom style sheet I can remove the border. This isn't what I was originally trying to accomplish, but I am satisfied with the result.

I still think Telerik might want to look into overriding global styles using external style sheets because it looks like you can't use an external style sheet to set a style back to its default value. I suppose I can open a support ticket and send you a sample project if you would like, but for my purposes the work-around described above is sufficient.
Tags
General Discussions
Asked by
Scott R
Top achievements
Rank 1
Answers by
Rossen Hristov
Telerik team
Scott R
Top achievements
Rank 1
Share this question
or