Silverlight printing sample

7336
52
05-25-2011 11:22 AM
DanDong
New Contributor
Hi everyone,

I am using the silverlight printing sample from code gallery (http://www.arcgis.com/home/item.html?id=e361c2cc69784fcba34358d0458f66e3).

According to the ReadMe, I should add a reference to the MapPrintingControls.dll (located at
MapPrintingControls/Bin/Release) to my silverlight application.

But I cannot find MapPrintingControls.dll in that path and neither the whole download folder, thus I cannot add this reference. Does anyone has clue for this? or if you have the dll, could you please share it with me 🙂 Really appreciate.
0 Kudos
52 Replies
DominiqueBroux
Esri Frequent Contributor

Text="{Binding Scale, RelativeSource={RelativeSource TemplatedParent}, StringFormat='1 : {0:F0} '}"


The sample is using this binding and is working, so difficult for me to help you out. The scale is supposed to be calculated and set in 'PreparePages'. I recommend you to test in debug and to set a breakpoint to this method, that could give a clue.
0 Kudos
DanDong
New Contributor
Hey Dominique, thank your for the tips. I see where the problem is. Actually I don't have 'PreparePages' function...so the scale doesn't get any value and it doesn't work I guess.

So I was thinking to add this function to MapPrinter loaded event. Please see the red words. But for some reasons the printExtent is always null. I put a breakpoint in this line: Envelope printExtent = mapPrinterWithDialog.PrintExtent....but it seems like there is no map in 'mapPrinterWithDialog' even I bind MyMap to its 'Map'. I am really confused...why the map is still empty after we bind its map property to MyMap, even in its loaded event?
controls:MapPrinterDialog x:Name="MapPrinterDialog" Background="White" Width="350" Height="400" Style="{StaticResource MyMapPrinterDialogStyle}" Visibility="Collapsed" >
                <controls:MapPrinter x:Name="mapPrinterWithDialog" Map="{Binding ElementName=MyMap}" Style="{StaticResource WithLegend}" 
                                     Title="WIRT" Loaded="mapPrinterWithDialog_Loaded"/>
                <!--IsScaleFixed="True" Scale="2000000"-->
                <!--IsActive="{Binding ElementName=PrintBtn }"-->
            </controls:MapPrinterDialog>           
            <controls:MapPrinterIndicator MapPrinter="{Binding ElementName=mapPrinter}" />


private void mapPrinterWithDialog_Loaded(object sender, RoutedEventArgs e)
        {
            MapPrinter mapPrinterWithDialog = sender as MapPrinter;

            double mapHeight = MyMap.ActualHeight;
            double mapWidth = MyMap.ActualWidth;
            Envelope printExtent = mapPrinterWithDialog.PrintExtent;
            var mapSize = new Size(mapPrinterWithDialog.RotateMap ? mapHeight : mapWidth, mapPrinterWithDialog.RotateMap ? mapWidth : mapHeight);
            var mapUnit = mapPrinterWithDialog.MapUnits;
            bool isWebMercator = (mapPrinterWithDialog.Map != null && mapPrinterWithDialog.Map.SpatialReference != null &&
                                  (mapPrinterWithDialog.Map.SpatialReference.WKID == 102100 || mapPrinterWithDialog.Map.SpatialReference.WKID == 102113 || mapPrinterWithDialog.Map.SpatialReference.WKID == 3857));
            double ratioScaleResolution = RatioScaleResolution(mapUnit, printExtent.GetCenter().Y, isWebMercator);
            double scale = mapPrinterWithDialog.Scale;
            double printResolution;

            printResolution = Math.Max(printExtent.Width / mapSize.Width, printExtent.Height / mapSize.Height);
            scale = ratioScaleResolution * printResolution;

            if (scale != mapPrinterWithDialog.Scale)
                mapPrinterWithDialog.Scale = scale;
        }


        private static double RatioScaleResolution(MapUnit mapUnit, double yCenter, bool isWebMercator)
        {
            double ratio;
            int dpi = 96;
            double toRadians = 0.017453292519943295769236907684886;
            double earthRadius = 6378137; //Earth radius in meters (defaults to WGS84 / GRS80)
            double degreeDist = earthRadius * toRadians;// distance of 1 degree at equator in meters

            if (isWebMercator)
            {
                // Transform yCenter from web mercator to decimal degree
                yCenter = Math.Min(Math.Max(yCenter, -20037508.3427892), 20037508.3427892);
                var point = new MapPoint(0, yCenter);
                yCenter = point.WebMercatorToGeographic().Y;
                ratio = Math.Cos(yCenter * toRadians) * dpi * 39.37; // 39.37 = MapUnit.Meters/MapUnit.Inches
            }
            else if (mapUnit == MapUnit.DecimalDegrees || mapUnit == MapUnit.Undefined)
            {
                if (Math.Abs(yCenter) > 90)
                    ratio = 0.0;
                else
                    ratio = Math.Cos(yCenter * toRadians) * degreeDist * dpi * 39.37;
            }
            else
            {
                ratio = (double)dpi * (int)mapUnit / (int)MapUnit.Inches;
            }
            return ratio;
        }
0 Kudos
DominiqueBroux
Esri Frequent Contributor
Actually I don't have 'PreparePages' function...so the scale doesn't get any value and it doesn't work I guess.


At first glance I don't see how the MapPrinter control could work without the PreparePages method.
I would recommend you to use the MapPrintingControls project as it is and just adapt the templates in your project (except if you think there is a missing functionality in MapPrintingControls?).
0 Kudos
DanDong
New Contributor
Hey Dominique, thank you for the advice. I still get this issue unfixed. But the user seems to want to omit this scale stuff. So shifted my attention to implement other functions.

I notice in the printing sample, the print button opens a standard Windows Print Dialog. So can I have another button similar to this one to open a standard windows SaveFile dialog?
0 Kudos
DominiqueBroux
Esri Frequent Contributor
But the user seems to want to omit this scale stuff. So shifted my attention to implement other functions.

You can just set IsScaleFixed to false.


So can I have another button similar to this one to open a standard windows SaveFile dialog?

You can use the standard SaveFileDialog provided by Silverlight. Note that for security reason, the SaveFileDialog can only be shown in response to an user initiated event (a button should be OK then).
0 Kudos
DanDong
New Contributor
You can use the standard SaveFileDialog provided by Silverlight. Note that for security reason, the SaveFileDialog can only be shown in response to an user initiated event (a button should be OK then).


Hey Dominique, thanks a lot for the answer. I just went through the codes. I am thinking to add a button just beside the 'Print' button, named 'Save'.
But I didn't find where I can specify the command to open a SaveFileDialog. I saw the 'Print' button is binded to a print command, but I didn't find where it is specified to open standard Windows PrintDialog.
Could you share some guidance? Thank you very much!
0 Kudos
ibrahimKalayci
New Contributor
Hi debroux,

i want to use your MapPrintingtool in my Silverlightapplication. I've done all the instructions step by step as in "readme.txt". But I get a runtime error: "[Control_TargetTypeMismatch]
"http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.60531.0&File=System.Windows.dll&Key=Contro...".
System.Windows.Controls.Control.ApplyTemplate()
Microsoft.Expression.Platform.Silverlight.InstanceBuilders.SilverlightViewNodeManager.EnsureElementInDictionary(Object root, ViewNode knownAncestor)"
0 Kudos
DominiqueBroux
Esri Frequent Contributor
Double check that all your references are correct.
Check also that you have added a reference to System.Windows.Controls.Toolkit in your application.
0 Kudos
PaulHuppé
Occasional Contributor
Hi Dominique,

I have downloaded your Map Printing solution because we need something like you developed.  I would have a few suggestions that you may have already considered or not.  In Canada, our applications must be bilingual, English and French, so it would be nice to have something like:

<controls:MapPrinter x:Name="mapPrinter"
        Map="{Binding ElementName=MyMap}"
        Locale="fr"
        Title="Tour de France 2010"
        IsScaleFixed="True" Scale="2000000"/>


This way, we could change the local on the fly.  This would mean that the MapPrinter control, or maybe this could be on the MapPrinterDialog control, would have to handle locales.  Another one, is that we have a requirement for a subtitle as well.

Next, when you click the Rotate Map checkbox, we get something like in the attached "img1_Default_Rotated.png".  We would need to rotate the whole template instead to have something like the modified image "img1_Default_Rotated_Modified.png".

Your thoughts,

Paul
0 Kudos
DominiqueBroux
Esri Frequent Contributor
Hi Paul,

Thanks for your suggestions.

The sources of this sample are provided so you can tweak it for your need.

My thoughts about your points:
   - localization : either keep the same mapprinter style whatever the locale and localize this style (likely with the same mechanism you are using for your application), or define one mapprinter style by locale, in this case your application has to select the right style depending on the current culture.
   - add a subtitle : you can add a new 'SubTitle' property  (like 'Title')
   - rotate the whole template : not sure it's needed. You will get the same result by printing the map in landscape mode.
0 Kudos