Bonjour à tous et merci de l'attention apporté a mon problème.

J'essai de mettre en place une solution d'impression de rapport en silverlight.
Pour cela j'utilise cette solution http://silverlightreporting.codeplex.com/.

Cette solution permet l'impression de rapport a l'aide de datatemplate.
On lui passe un ItemSource, on créer des datatemplates pour l'agencement de nos données et cela permet de faire une belle mise en page lors de l'impression.

Comme le sujet l'indique, j'ai un soucis avec un RelativeSource Binding qui ne semble pas fonctionner.

Je vous présente mon projet:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
 
<Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
 
        <sdk:DataGrid x:Name="datagGrid">
        </sdk:DataGrid>
 
        <Button Content="Print" Grid.Row="1" Click="Button_Click"/>
 
        <printing:Report x:Name="TestControl" DateVisibility="Collapsed">
 
            <printing:Report.Resources>
                <!-- Référence vers mon Converter pour tenter de debugger le binding -->
                <ResourceDictionary Source="Styles.xaml"/>
            </printing:Report.Resources>
 
 
            <printing:Report.PageHeaderTemplate>
               ...
            </printing:Report.PageHeaderTemplate>
 
            <printing:Report.ItemTemplate>
                <DataTemplate>
                    <Grid HorizontalAlignment="Stretch" Margin="5 0 0 20">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="200" />
                            <ColumnDefinition Width="200" />
                            <ColumnDefinition Width="150" />
                            <ColumnDefinition Width="150" />
                        </Grid.ColumnDefinitions>
 
                        <TextBlock Text="{Binding Path=AlarmName, StringFormat='\{0}, '}" FontWeight="Bold" />
 
                        <TextBlock Grid.Column="1" Text="{Binding Path=Type}" TextAlignment="Center" />
 
                        <TextBlock Grid.Column="2" Text="{Binding Path=State}" TextAlignment="Right" 
                                   Visibility="{Binding Path=DateVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=printing:Report}, Converter={StaticResource ResourceKey=DebugConverter}}"/>
 
                        <TextBlock Grid.Column="3" Text="{Binding Path=Device}" TextAlignment="Right" />
 
                        <StackPanel Grid.Row="1" Orientation="Horizontal" Grid.ColumnSpan="4">
                            <TextBlock Text="Event Description: " />
                        </StackPanel>
 
                        <TextBlock Grid.Row="2" Grid.ColumnSpan="4" TextWrapping="Wrap" Text="{Binding Path=ReviewComments}" />
                    </Grid>
                </DataTemplate>
            </printing:Report.ItemTemplate>
 
            <printing:Report.PageFooterTemplate>
                ...
            </printing:Report.ReportFooterTemplate>
        </printing:Report>
 
 
    </Grid>
Donc pour vous expliquer. Ici j'ai mon projet avec une simple datagrid, dont le datacontext est une liste d'objet Alarme.
En dessous j'inclus le contrôle Report de la solution d'impression que je vous ai présenté au début.
Enfin je créer les DataTemplates nécessaire à l'impression.

Celui qui nous intéresse ici, c'est l'ItemTemplate. Son DataContext est ma liste d'Alarme. Or j'essai de bind la visibilité d'un de mes Textblock sur la propriété de dépendance DateVisibilty de mon contrôle Report.
j'ai vu que pour cela il fallait utiliser RelativeSource qui permettait de Bind sur une propriété d'un contrôle parent. Malheureusement ça ne marche pas, et je n'arrive pas à trouver de solution car j'ai vraiment l'impression d'utiliser la bonne méthode et j'ai réussi à le faire dans un autre projet (mais pas en utilisant cette solution d'impression).
Je me demande donc si le problème ne viendrais pas de la solution d'impression, mais pareil, je n'arrive pas a voir où ça pourrait bloquer.

Voici la classe Report:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
 
public class Report : FrameworkElement
    {
        public DataTemplate PageHeaderTemplate
        {
            get { return (DataTemplate)GetValue(PageHeaderTemplateProperty); }
            set { SetValue(PageHeaderTemplateProperty, value); }
        }
 
        public static readonly DependencyProperty PageHeaderTemplateProperty =
            DependencyProperty.Register("PageHeaderTemplate", typeof(DataTemplate), typeof(Report), new PropertyMetadata(null));
 
 
        public DataTemplate PageFooterTemplate
        {
            get { return (DataTemplate)GetValue(PageFooterTemplateProperty); }
            set { SetValue(PageFooterTemplateProperty, value); }
        }
 
        public static readonly DependencyProperty PageFooterTemplateProperty =
            DependencyProperty.Register("PageFooterTemplate", typeof(DataTemplate), typeof(Report), new PropertyMetadata(null));
 
 
        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate)GetValue(ItemTemplateProperty); }
            set { SetValue(ItemTemplateProperty, value); }
        }
 
        public static readonly DependencyProperty ItemTemplateProperty =
            DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(Report), new PropertyMetadata(null));
 
 
        public DataTemplate ReportFooterTemplate
        {
            get { return (DataTemplate)GetValue(ReportFooterTemplateProperty); }
            set { SetValue(ReportFooterTemplateProperty, value); }
        }
 
        public static readonly DependencyProperty ReportFooterTemplateProperty =
            DependencyProperty.Register("ReportFooterTemplate", typeof(DataTemplate), typeof(Report), new PropertyMetadata(null));
 
 
 
        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }
 
        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(Report), new PropertyMetadata(null));
 
 
 
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }
 
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(Report), new PropertyMetadata("Report"));
 
 
 
        //#region Columns Visibility
        public Visibility DateVisibility
        {
            get { return (Visibility)GetValue(DateVisibilityProperty); }
            set { SetValue(DateVisibilityProperty, value); }
        }
 
        public static readonly DependencyProperty DateVisibilityProperty =
            DependencyProperty.Register("DateVisibility", typeof(Visibility), typeof(Report), new PropertyMetadata(null));
 
 
 
 
 
        public int CurrentPageNumber
        {
            get { return (int)GetValue(CurrentPageNumberProperty); }
            private set { SetValue(CurrentPageNumberProperty, value); }
        }
 
        public static readonly DependencyProperty CurrentPageNumberProperty =
            DependencyProperty.Register("CurrentPageNumber", typeof(int), typeof(Report), new PropertyMetadata(0));
 
 
 
        public int TotalPageCount
        {
            get { return (int)GetValue(TotalPageCountProperty); }
            private set { SetValue(TotalPageCountProperty, value); }
        }
 
        public static readonly DependencyProperty TotalPageCountProperty =
            DependencyProperty.Register("TotalPageCount", typeof(int), typeof(Report), new PropertyMetadata(0));
 
 
 
        private PrintDocument _printDocument = new PrintDocument();
        public PrintDocument PrintDocument
        {
            get { return _printDocument; }
        }
 
 
        public event EventHandler EndPrint;
        protected void OnEndPrint(EventArgs args)
        {
            if (EndPrint != null)
                EndPrint(this, args);
        }
 
        public event EventHandler BeginPrint;
        protected void OnBeginPrint(EventArgs args)
        {
            if (BeginPrint != null)
                BeginPrint(this, args);
        }
 
        public event EventHandler EndBuildReport;
        protected void OnEndBuildReport(EventArgs args)
        {
            if (EndBuildReport != null)
                EndBuildReport(this, args);
        }
 
        public event EventHandler BeginBuildReport;
        protected void OnBeginBuildReport(EventArgs args)
        {
            if (BeginBuildReport != null)
                BeginBuildReport(this, args);
        }
 
        public event EventHandler EndBuildReportItem;
        protected void OnEndBuildReportItem(EventArgs args)
        {
            if (EndBuildReportItem != null)
                EndBuildReportItem(this, args);
        }
 
        public event EventHandler<PrintingEventArgs> BeginBuildReportItem;
        protected void OnBeginBuildReportItem(PrintingEventArgs args)
        {
            if (BeginBuildReportItem != null)
                BeginBuildReportItem(this, args);
        }
 
        public event EventHandler<PrintingEventArgs> BeginBuildReportFooter;
        protected void OnBeginBuildReportFooter(PrintingEventArgs args)
        {
            if (BeginBuildReportFooter != null)
                BeginBuildReportFooter(this, args);
        }
 
 
 
        private int _pageTreeIndex = 0;
        private void PrintDocumentPrintPageHandler(object sender, PrintPageEventArgs e)
        {
 
            if (_pageTreeIndex == 0)
            {
                BuildReport(e.PrintableArea);
                TotalPageCount = _pageTrees.Count;
                CurrentPageNumber = 0;
            }
 
            if (_pageTrees.Count > 0)
            {
                CurrentPageNumber++;
                e.PageVisual = _pageTrees[_pageTreeIndex];
            }
 
            e.HasMorePages = _pageTreeIndex < _pageTrees.Count - 1;
 
            _pageTreeIndex++;
        }
 
        private void PrintDocumentBeginPrintHandler(object sender, BeginPrintEventArgs e)
        {
            OnBeginPrint(EventArgs.Empty);
        }
 
        private void PrintDocumentEndPrintHandler(object sender, EndPrintEventArgs e)
        {
            OnEndPrint(EventArgs.Empty);
 
            // remove event handlers so we don't have any references hanging around
            _printDocument.PrintPage -= PrintDocumentPrintPageHandler;
            _printDocument.BeginPrint -= PrintDocumentBeginPrintHandler;
            _printDocument.EndPrint -= PrintDocumentEndPrintHandler;
        }
 
        public void Print()
        {
            Print(null);
        }
 
        public void Print(PrinterFallbackSettings settings)
        {
            CurrentPageNumber = 0;
            _pageTreeIndex = 0;
 
            _printDocument.PrintPage += PrintDocumentPrintPageHandler;
            _printDocument.BeginPrint += PrintDocumentBeginPrintHandler;
            _printDocument.EndPrint += PrintDocumentEndPrintHandler;
 
            if (settings != null)
                _printDocument.Print(Title.Replace(" ", ""), settings);
            else
                _printDocument.Print(Title.Replace(" ", ""));
        }
 
 
        private List<UIElement> _pageTrees = new List<UIElement>();
 
        // Pre-calculates pages. This allows for total page count
        // as well as better handling of page breaks, and eventual
        // inclusion of groups and whatnot. If this takes too long, though
        // it'll exceed the timeout and make the printing fail in a 
        // sandboxed silverlight application. Alternative would be to make
        // printing a two-step operation: First, build report, Second, user 
        // clicks button to do the actual printing. That approach 
        // introduces issues with data changing in-between the steps.
        private void BuildReport(Size printableArea)
        {
            _pageTrees.Clear();
            CurrentPageNumber = 0;
 
            OnBeginBuildReport(EventArgs.Empty);
 
            if (ItemsSource == null)
                return;
 
            IEnumerable reportItems = ItemsSource;
            IEnumerator reportItemsEnumerator = reportItems.GetEnumerator();
 
            reportItemsEnumerator.Reset();
 
            StackPanel itemsPanel = null;
            Grid pagePanel = null;
            Size itemsPanelMaxSize = new Size();
 
            // create first page
            pagePanel = GetNewPage(printableArea, out itemsPanel, out itemsPanelMaxSize);
 
            // add the items
            while (reportItemsEnumerator.MoveNext())
            {
                object currentItem = reportItemsEnumerator.Current;
 
                PrintingEventArgs args = new PrintingEventArgs();
                args.DataContext = currentItem;
                OnBeginBuildReportItem(args);
 
                // create row. Set data context.
                FrameworkElement row = ItemTemplate.LoadContent() as FrameworkElement;
                row.DataContext = args.DataContext;
 
                // ContentPresenter approach was tried to see if it helped resolve Run
                // inlines with binding. No go.
                //ContentPresenter row = new ContentPresenter();
                //row.ContentTemplate = ItemTemplate;
                //row.Content = currentItem;
 
                row.Measure(printableArea);
 
                // create a new page if we're out of room here
                if (row.DesiredSize.Height + itemsPanel.DesiredSize.Height > itemsPanelMaxSize.Height)
                {
                    pagePanel = GetNewPage(printableArea, out itemsPanel, out itemsPanelMaxSize);
                }
 
                itemsPanel.Children.Add(row);
                itemsPanel.Measure(printableArea);
            }
 
            // create report footer. This goes at the very end of the report and typically
            // includes totals and other summary information
            if (ReportFooterTemplate != null)
            {
                PrintingEventArgs reportFooterEventArgs = new PrintingEventArgs();
                reportFooterEventArgs.DataContext = this;
                OnBeginBuildReportFooter(reportFooterEventArgs);
 
                FrameworkElement reportFooter = ReportFooterTemplate.LoadContent() as FrameworkElement;
                if (reportFooter != null)
                {
                    reportFooter.DataContext = reportFooterEventArgs.DataContext;
                    reportFooter.Measure(printableArea);
 
                    // fit the footer into the report
                    if (reportFooter.DesiredSize.Height + itemsPanel.DesiredSize.Height > itemsPanelMaxSize.Height)
                    {
                        pagePanel = GetNewPage(printableArea, out itemsPanel, out itemsPanelMaxSize);
                    }
 
                    itemsPanel.Children.Add(reportFooter);
                }
            }
 
            OnEndBuildReport(EventArgs.Empty);
 
        }
 
 
        private Grid GetNewPage(Size printableArea, out StackPanel itemsPanel, out Size itemsPanelMaxSize)
        {
            const int HeaderGridRowNumber = 0;
            const int BodyGridRowNumber = 1;
            const int FooterGridRowNumber = 2;
 
            CurrentPageNumber++;
 
            Grid pagePanel = new Grid();
            RowDefinition headerRow = new RowDefinition();
            headerRow.Height = GridLength.Auto;
 
            pagePanel.Background = new SolidColorBrush { Color = Colors.White };
 
            RowDefinition itemsRow = new RowDefinition();
            itemsRow.Height = new GridLength(1, GridUnitType.Star);
 
            RowDefinition footerRow = new RowDefinition();
            footerRow.Height = GridLength.Auto;
 
            pagePanel.RowDefinitions.Add(headerRow);
            pagePanel.RowDefinitions.Add(itemsRow);
            pagePanel.RowDefinitions.Add(footerRow);
 
            // page header. Typically includes column headers and whatnot
            double headerDesiredHeight = 0;
            if (PageHeaderTemplate != null)
            {
                FrameworkElement header = PageHeaderTemplate.LoadContent() as FrameworkElement;
                header.DataContext = this;
                Grid.SetRow(header, HeaderGridRowNumber);
                pagePanel.Children.Add(header);
                header.Measure(new Size(printableArea.Width, printableArea.Height));
 
                headerDesiredHeight = header.DesiredSize.Height;
            }
 
            // create body to fit in between
            itemsPanel = new StackPanel();
            itemsPanel.Orientation = Orientation.Vertical;
            itemsPanel.HorizontalAlignment = HorizontalAlignment.Stretch;
            itemsPanel.VerticalAlignment = VerticalAlignment.Top;
            itemsPanel.Background = new SolidColorBrush { Color = Colors.White };
            Grid.SetRow(itemsPanel, BodyGridRowNumber);
            pagePanel.Children.Add(itemsPanel);
 
 
            // create page footer. Typically includes the page number
            double footerDesiredHeight = 0;
            if (PageFooterTemplate != null)
            {
                FrameworkElement footer = PageFooterTemplate.LoadContent() as FrameworkElement;
                footer.DataContext = this;
                Grid.SetRow(footer, FooterGridRowNumber);
                pagePanel.Children.Add(footer);
                footer.Measure(new Size(printableArea.Width, printableArea.Height));
 
                footerDesiredHeight = footer.DesiredSize.Height;
            }
 
            itemsPanelMaxSize = new Size(printableArea.Width, printableArea.Height - footerDesiredHeight - headerDesiredHeight);
 
            _pageTrees.Add(pagePanel);
 
            return pagePanel;
        }
 
 
    }

Si je n'ai pas été clair ou si vous souhaiteriez avoir les sources de mon projet pour tester vous mêmes n'hésitais pas à me demander.
De même si vous voulez simplement des éclaircissement sur le fonctionnement de cette solution d'impression je suis a votre disposition.

En vous remerciant de votre aide!