~ubuntu-branches/ubuntu/karmic/moon/karmic

« back to all changes in this revision

Viewing changes to class/Microsoft.SilverlightControls/Controls/Src/ContentControl/ContentPresenter.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2009-02-14 12:01:08 UTC
  • Revision ID: james.westby@ubuntu.com-20090214120108-06539vb25vhbd8bn
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
ļ»æ// Copyright Ā© Microsoft Corporation. 
 
2
// This source is subject to the Microsoft Source License for Silverlight Controls (March 2008 Release).
 
3
// Please see http://go.microsoft.com/fwlink/?LinkID=111693 for details.
 
4
// All other rights reserved. 
 
5
 
 
6
using System;
 
7
using System.ComponentModel; 
 
8
using System.Diagnostics; 
 
9
using System.Windows.Documents;
 
10
using System.Windows.Markup; 
 
11
using System.Windows.Media;
 
12
using System.Windows.Controls;
 
13
 
 
14
namespace System.Windows.Controls
 
15
{
 
16
    /// <summary>
 
17
    /// Displays the content of a ContentControl. 
 
18
    /// </summary> 
 
19
    /// <remarks>
 
20
    /// Typically, you the ContentPresenter directly within the ControlTemplate 
 
21
    /// of a ContentControl to mark where the content should be displayed.
 
22
    /// Every type derived from ContentControl should have a ContentPrenter in
 
23
    /// its ControlTemplate (although it may not necessarily be a TemplatePart). 
 
24
    /// The ContentPresenter in the ControlTemplate should use a TemplateBinding
 
25
    /// to associate ContentControl.Content with ContentPresenter.Content (and
 
26
    /// an other relevant properties like FontSize, VeriticalAlignment, etc.). 
 
27
    /// </remarks> 
 
28
    public class ContentPresenter : Control
 
29
    { 
 
30
        /// <summary>
 
31
        /// XAML markup used to define the write-once ContentPresenter template.
 
32
        /// </summary> 
 
33
        private const string ContentPresenterDefaultTemplate =
 
34
            "<ControlTemplate " +
 
35
              "xmlns=\"http://schemas.microsoft.com/client/2007\" " + 
 
36
              "xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" " + 
 
37
              "xmlns:controls=\"clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls\" " +
 
38
              "TargetType=\"controls:ContentPresenter\">" + 
 
39
                "<Grid x:Name=\"RootElement\" " +
 
40
                  "Background=\"{TemplateBinding Background}\" " +
 
41
                  "Cursor=\"{TemplateBinding Cursor}\">" + 
 
42
                    "<TextBlock x:Name=\"TextElement\" " +
 
43
                      "FontFamily=\"{TemplateBinding FontFamily}\" " +
 
44
                      "FontSize=\"{TemplateBinding FontSize}\" " + 
 
45
                      "FontStretch=\"{TemplateBinding FontStretch}\" " + 
 
46
                      "FontStyle=\"{TemplateBinding FontStyle}\" " +
 
47
                      "FontWeight=\"{TemplateBinding FontWeight}\" " + 
 
48
                      "Foreground=\"{TemplateBinding Foreground}\" " +
 
49
                      "HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" " +
 
50
                      "Padding=\"{TemplateBinding Padding}\" " + 
 
51
                      "TextAlignment=\"{TemplateBinding TextAlignment}\" " +
 
52
                      "TextDecorations=\"{TemplateBinding TextDecorations}\" " +
 
53
                      "TextWrapping=\"{TemplateBinding TextWrapping}\" " + 
 
54
                      "VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" " + 
 
55
                      "Visibility=\"Collapsed\" />" +
 
56
                "</Grid>" + 
 
57
            "</ControlTemplate>";
 
58
 
 
59
        /// <summary> 
 
60
        /// Root element of the panel that will contain the visual content.
 
61
        /// </summary>
 
62
        /// <remarks> 
 
63
        /// Since a Control cannot change its content (i.e. it may only call 
 
64
        /// InitializeFromXaml once to set its root), every ContentPresetner
 
65
        /// will create a container as its root element regardless of the 
 
66
        /// content that will be stuffed into it.  It's also worth noting that
 
67
        /// there is no TemplatePartAttribute because the Template is write-once
 
68
        /// and cannot be changed by users.  This field is marked internal for 
 
69
        /// unit testing.
 
70
        /// </remarks>
 
71
        internal Grid _elementRoot; 
 
72
        internal const string RootElementName = "RootElement"; 
 
73
 
 
74
        /// <summary> 
 
75
        /// Visual representation of the Content currently being displayed.
 
76
        /// </summary>
 
77
        /// <remarks>This field is marked internal for unit testing.</remarks> 
 
78
        internal UIElement _elementContent;
 
79
 
 
80
        /// <summary> 
 
81
        /// Visual representation of any text Content currently being displayed. 
 
82
        /// </summary>
 
83
        /// <remarks> 
 
84
        /// The _elementText property is necessary in addition to the
 
85
        /// _elementContent property because of all of all the font related
 
86
        /// properties whose values need to be propogated into it by the 
 
87
        /// ContentPresenter.  This field is marked internal for unit testing.
 
88
        /// </remarks>
 
89
        internal TextBlock _elementText; 
 
90
        internal const string ElementTextContentName = "TextElement"; 
 
91
 
 
92
        /// <summary> 
 
93
        /// True if the template has already been applied, false otherwise.
 
94
        /// </summary>
 
95
        internal bool _alreadyAppliedTemplate; 
 
96
 
 
97
        #region Content
 
98
        /// <summary> 
 
99
        /// Gets or sets the data used to generate the contentPresenter elements of a 
 
100
        /// ContentPresenter.
 
101
        /// </summary> 
 
102
        public object Content
 
103
        {
 
104
            get { return GetValue(ContentProperty); } 
 
105
            set { SetValue(ContentProperty, value); }
 
106
        }
 
107
 
 
108
        /// <summary> 
 
109
        /// Identifies the Content dependency property.
 
110
        /// </summary> 
 
111
        public static readonly DependencyProperty ContentProperty =
 
112
            DependencyProperty.Register(
 
113
                "Content", 
 
114
                typeof(object),
 
115
                typeof(ContentPresenter),
 
116
                new PropertyMetadata(OnContentPropertyChanged)); 
 
117
 
 
118
        /// <summary>
 
119
        /// ContentProperty property changed handler. 
 
120
        /// </summary>
 
121
        /// <param name="d">ContentPresenter that changed its Content.</param>
 
122
        /// <param name="e">DependencyPropertyChangedEventArgs.</param> 
 
123
        private static void OnContentPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
 
124
        {
 
125
            ContentPresenter source = d as ContentPresenter; 
 
126
            Debug.Assert(source != null, 
 
127
                "The source is not an instance of ContentPresenter!");
 
128
 
 
129
            // Use the Content as the DataContext to enable bindings in
 
130
            // ContentTemplate
 
131
            if (source.ContentTemplate != null) 
 
132
            {
 
133
                source.DataContext = e.NewValue;
 
134
            } 
 
135
 
 
136
            // Display the Content
 
137
            source.PrepareContentPresenter(); 
 
138
        }
 
139
        #endregion Content
 
140
 
 
141
        #region ContentTemplate
 
142
        /// <summary>
 
143
        /// Gets or sets the data template used to display the content of the 
 
144
        /// ContentPresenter. 
 
145
        /// </summary>
 
146
        public DataTemplate ContentTemplate 
 
147
        {
 
148
            get { return GetValue(ContentTemplateProperty) as DataTemplate; }
 
149
            set { SetValue(ContentTemplateProperty, value); } 
 
150
        }
 
151
 
 
152
        /// <summary> 
 
153
        /// Identifies the ContentTemplate dependency property. 
 
154
        /// </summary>
 
155
        public static readonly DependencyProperty ContentTemplateProperty = 
 
156
            DependencyProperty.Register(
 
157
                "ContentTemplate",
 
158
                typeof(DataTemplate), 
 
159
                typeof(ContentPresenter),
 
160
                new PropertyMetadata(OnContentTemplatePropertyChanged));
 
161
 
 
162
        /// <summary> 
 
163
        /// ContentTemplateProperty property changed handler.
 
164
        /// </summary> 
 
165
        /// <param name="d">ContentPresenter that changed its ContentTemplate.</param>
 
166
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
 
167
        private static void OnContentTemplatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
 
168
        {
 
169
            ContentPresenter source = d as ContentPresenter;
 
170
            Debug.Assert(source != null, 
 
171
                "The source is not an instance of ContentPresenter!"); 
 
172
 
 
173
            // Use the Content as the DataContext to enable bindings in 
 
174
            // ContentTemplate or clear it if we removed our template (NOTE:
 
175
            // this should use ClearValue instead when it's available).
 
176
            source.DataContext = e.NewValue != null ? source.Content : null; 
 
177
 
 
178
            // Display the Content
 
179
            source.PrepareContentPresenter(); 
 
180
        } 
 
181
        #endregion ContentTemplate
 
182
 
 
183
        #region TextAlignment 
 
184
        /// <summary>
 
185
        /// Gets or sets a value that indicates the horizontal alignment of text
 
186
        /// content. 
 
187
        /// </summary>
 
188
        public TextAlignment TextAlignment
 
189
        { 
 
190
            get { return (TextAlignment) GetValue(TextAlignmentProperty); } 
 
191
            set { SetValue(TextAlignmentProperty, value); }
 
192
        } 
 
193
 
 
194
        /// <summary>
 
195
        /// Identifies the TextAlignment dependency property. 
 
196
        /// </summary>
 
197
        public static readonly DependencyProperty TextAlignmentProperty =
 
198
            DependencyProperty.Register( 
 
199
                "TextAlignment", 
 
200
                typeof(TextAlignment),
 
201
                typeof(ContentPresenter), 
 
202
                null);
 
203
        #endregion TextAlignment
 
204
 
 
205
        #region TextDecorations
 
206
        /// <summary>
 
207
        /// Gets or sets a TextDecorationCollection that contains the effects to 
 
208
        /// apply to the Content text. 
 
209
        /// </summary>
 
210
        [TypeConverter(typeof(TextDecorationCollectionConverter))] 
 
211
        public TextDecorationCollection TextDecorations
 
212
        {
 
213
            get { return GetValue(TextDecorationsProperty) as TextDecorationCollection; } 
 
214
            set { SetValue(TextDecorationsProperty, value); }
 
215
        }
 
216
 
 
217
        /// <summary> 
 
218
        /// Identifies the TextDecorations dependency property.
 
219
        /// </summary> 
 
220
        public static readonly DependencyProperty TextDecorationsProperty =
 
221
            DependencyProperty.Register(
 
222
                "TextDecorations", 
 
223
                typeof(TextDecorationCollection),
 
224
                typeof(ContentPresenter),
 
225
                null); 
 
226
        #endregion TextDecorations 
 
227
 
 
228
        #region TextWrapping 
 
229
        /// <summary>
 
230
        /// Gets or sets a value that indicates how the TextBlock should wrap
 
231
        /// text. 
 
232
        /// </summary>
 
233
        public TextWrapping TextWrapping
 
234
        { 
 
235
            get { return (TextWrapping) GetValue(TextWrappingProperty); } 
 
236
            set { SetValue(TextWrappingProperty, value); }
 
237
        } 
 
238
 
 
239
        /// <summary>
 
240
        /// Identifies the TextWrapping dependency property. 
 
241
        /// </summary>
 
242
        public static readonly DependencyProperty TextWrappingProperty =
 
243
            DependencyProperty.Register( 
 
244
                "TextWrapping", 
 
245
                typeof(TextWrapping),
 
246
                typeof(ContentPresenter), 
 
247
                null);
 
248
        #endregion TextWrapping
 
249
 
 
250
        /// <summary>
 
251
        /// Initializes a new instance of the ContentPresenter class.
 
252
        /// </summary> 
 
253
        public ContentPresenter() 
 
254
        {
 
255
            // Apply the default Template to ContentPresenter. 
 
256
            Template = XamlReader.Load(ContentPresenterDefaultTemplate) as ControlTemplate;
 
257
            ApplyTemplate();
 
258
            Debug.Assert(_alreadyAppliedTemplate, 
 
259
                "The write-once Template flag _alreadyAppliedTemplate was not set!");
 
260
        }
 
261
 
 
262
        /// <summary> 
 
263
        /// Apply the default Template to ContentPresenter.  This is only
 
264
        /// allowed to happen one time. 
 
265
        /// </summary>
 
266
        public override void OnApplyTemplate()
 
267
        { 
 
268
            // Ensure that the Template property is set/applied only once (from
 
269
            // our constructor).
 
270
            if (_alreadyAppliedTemplate) 
 
271
            { 
 
272
                throw new InvalidOperationException(Resource.ContentPresenter_OnApplyTemplate_WriteOnce);
 
273
            } 
 
274
            _alreadyAppliedTemplate = true;
 
275
 
 
276
            // Get the content root and the text content visual 
 
277
            _elementRoot = GetTemplateChild(RootElementName) as Grid;
 
278
            Debug.Assert(_elementRoot != null,
 
279
                "The required template part RootElement was not found!"); 
 
280
 
 
281
            _elementText = GetTemplateChild(ElementTextContentName) as TextBlock;
 
282
            Debug.Assert(_elementText != null, 
 
283
                "The required template part TextElement is not an instance of TextBlock!");
 
284
 
 
285
            // Ensure the template parts were structured correctly 
 
286
            Debug.Assert(_elementContent == null,
 
287
                "_elementContent should not exist when applying the template!");
 
288
            Debug.Assert(_elementRoot.Children.Contains(_elementText), 
 
289
                "TextElement should be a child of RootElement!"); 
 
290
            Debug.Assert(_elementRoot.Children.Count == 1,
 
291
                "RootElement should have TextElement as its only child!"); 
 
292
        }
 
293
 
 
294
        /// <summary> 
 
295
        /// Update the ContentPresenter's logical tree with the appropriate
 
296
        /// visual elements when its Content is changed.
 
297
        /// </summary> 
 
298
        private void PrepareContentPresenter() 
 
299
        {
 
300
            Debug.Assert(_elementRoot != null, "RootElement is null!"); 
 
301
            Debug.Assert(_elementText != null, "TextElement is null!");
 
302
 
 
303
            // Remove the old content 
 
304
            if (_elementContent != _elementText)
 
305
            {
 
306
                _elementRoot.Children.Remove(_elementContent); 
 
307
                _elementContent = null; 
 
308
            }
 
309
            else 
 
310
            {
 
311
                _elementText.Text = null;
 
312
            } 
 
313
 
 
314
            // Expand the ContentTemplate if it exists
 
315
            DataTemplate template = ContentTemplate; 
 
316
            object content = (template != null) ? 
 
317
                template.LoadContent() :
 
318
                Content; 
 
319
 
 
320
            // Add the new content
 
321
            UIElement element = content as UIElement; 
 
322
            if (element != null)
 
323
            {
 
324
                _elementContent = element; 
 
325
                _elementRoot.Children.Add(_elementContent); 
 
326
                _elementText.Visibility = Visibility.Collapsed;
 
327
            } 
 
328
            else if (content != null)
 
329
            {
 
330
                _elementText.Visibility = Visibility.Visible; 
 
331
//
 
332
                _elementText.Text = content.ToString();
 
333
            } 
 
334
            else 
 
335
            {
 
336
                _elementText.Visibility = Visibility.Collapsed; 
 
337
            }
 
338
        }
 
339
 
 
340
        /// <summary>
 
341
        /// Returns the specified contentPresenter element.
 
342
        /// </summary> 
 
343
        /// <param name="index">The index of the desired contentPresenter.</param> 
 
344
        /// <returns>The contentPresenter element at the specified index value.</returns>
 
345
        protected virtual DependencyObject GetVisualChild(int index) 
 
346
        {
 
347
            if (index != 0)
 
348
            { 
 
349
                throw new ArgumentOutOfRangeException("index");
 
350
            }
 
351
 
 
352
            object content = Content; 
 
353
            return (content == null) ?
 
354
                null : 
 
355
                ((content is UIElement) ?
 
356
                    _elementContent :
 
357
                    _elementText); 
 
358
        }
 
359
    }
 
360