Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Markup / TemplateApplicationHelper.cs / 2 / TemplateApplicationHelper.cs
/****************************************************************************\
*
* File: TemplateApplicationHelper.cs
*
* Copyright (C) 2005 by Microsoft Corporation. All rights reserved.
*
\***************************************************************************/
using MS.Internal;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Markup;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Controls;
using System.Collections.Specialized;
namespace System.Windows
{
//+---------------------------------------------------------------------------------------------
//
// Class TemplateApplicationHelper
//
// This class is a BamlRecordReader which is used to help instantiate a template.
// This BamlRecordReader is used to instantiate the unshareable content of the template,
// and we override SetDependencyValue here so that we can set values into
// the FE's special store for ParentTemplate values.
//
//+---------------------------------------------------------------------------------------------
internal class TemplateApplicationHelper : BamlRecordReader
{
internal TemplateApplicationHelper ( )
{
RootList = new ArrayList(1);
}
//
// Initialization is separate from the constructer so that it can be called
// repeatedly.
//
internal void Initialize( ParserContext parserContext, object templatedParent )
{
ParserContext = parserContext;
_templatedParent = (DependencyObject) templatedParent;
RootElement = null;
if( RootList != null )
{
RootList.Clear();
}
ContextStack.Clear();
ComponentConnector = null;
}
/***************************************************************************\
*
* TemplateBamlRecordReader.ReadDeferableContentStart
*
* Called when parsing the deferable content start element.
* When we have a ResourceDictionary inside template content,
* we need to retrieve the cached values buffer and supply it
* do the ResourceDictionary so that it can use it to
* RealizeDeferredContent.
*
\***************************************************************************/
internal override void ReadDeferableContentStart(
BamlDeferableContentStartRecord bamlRecord)
{
ResourceDictionary dictionary = GetDictionaryFromContext(CurrentContext, true /*toInsert*/) as ResourceDictionary;
if (dictionary != null)
{
// Read and create the keys and the static resource
// objects for this dictionary
ArrayList defKeyList;
List staticResourceValuesList;
BaseReadDeferableContentStart(bamlRecord, out defKeyList, out staticResourceValuesList);
// Supply the keys, static resources and values buffer to the
// dictionary so it can use it to realize deferred content.
dictionary.SetDeferableContent(bamlRecord.ValuesBuffer, ParserContext, RootElement, defKeyList, staticResourceValuesList);
}
}
//+------------------------------------------------------------------------------------------------------------
//
// SetDependencyValue (override)
//
// If a DP value is being set onto an FE/FCE that is being optimized as part of a template, put the
// value into the special ParentTemplate state.
//
//+-----------------------------------------------------------------------------------------------------------
internal override void SetDependencyValueCore(DependencyObject dependencyObject, DependencyProperty dp, object value )
{
FrameworkObject fo = new FrameworkObject(dependencyObject);
// If this isn't an FE that we're optimizing, defer to base.
//
// Similarly, if we don't have a templated parent, we're not optimizing, and defer to base
// (This happens when FrameworkTemplate.LoadContent() is called.)
if ((fo.TemplatedParent == null) || ( _templatedParent == null ))
{
base.SetDependencyValueCore( dependencyObject, dp, value );
return;
}
// For template content, we skip the automatic BaseUriProperty and the UidProperty
// (Implementation note: Doing this here because this is what we did with FEFs,
// and because automation gets confused if the Uid isn't unique in the whole tree).
if( dp == System.Windows.Navigation.BaseUriHelper.BaseUriProperty )
{
// We only skip the automatic BaseUri property. If it's set explicitely,
// that's passed through.
if (!fo.IsInitialized)
{
return;
}
}
else if (dp == UIElement.UidProperty)
{
return;
}
#if DEBUG
Debug.Assert(fo.TemplatedParent == _templatedParent);
#endif
// Set the value onto the FE/FCE.
HybridDictionary parentTemplateValues;
if (!fo.StoresParentTemplateValues)
{
parentTemplateValues = new HybridDictionary();
StyleHelper.ParentTemplateValuesField.SetValue(dependencyObject, parentTemplateValues);
fo.StoresParentTemplateValues = true;
}
else
{
parentTemplateValues = StyleHelper.ParentTemplateValuesField.GetValue(dependencyObject);
}
// Check if it is an expression
Expression expr;
int childIndex = fo.TemplateChildIndex;
if ((expr = value as Expression) != null)
{
BindingExpressionBase bindingExpr;
TemplateBindingExpression templateBindingExpr;
if ((bindingExpr = expr as BindingExpressionBase) != null)
{
// If this is a BindingExpression then we need to store the corresponding
// MarkupExtension into the per instance store for the unshared DP value.
// Allocate a slot for this unshared DP value in the per-instance store for MarkupExtensions
HybridDictionary instanceValues = StyleHelper.EnsureInstanceData(StyleHelper.TemplateDataField, _templatedParent, InstanceStyleData.InstanceValues);
StyleHelper.ProcessInstanceValue(dependencyObject, childIndex, instanceValues, dp, StyleHelper.UnsharedTemplateContentPropertyIndex, true /*apply*/);
value = bindingExpr.ParentBindingBase;
}
else if ((templateBindingExpr = expr as TemplateBindingExpression) != null)
{
// If this is a TemplateBindingExpression then we create an equivalent Binding
// MarkupExtension and store that in the per instance store for the unshared DP
// value. We use Binding here because it has all the wiring in place to handle
// change notifications through DependencySource and such.
TemplateBindingExtension templateBindingExtension = templateBindingExpr.TemplateBindingExtension;
// Allocate a slot for this unshared DP value in the per-instance store for MarkupExtensions
HybridDictionary instanceValues = StyleHelper.EnsureInstanceData(StyleHelper.TemplateDataField, _templatedParent, InstanceStyleData.InstanceValues);
StyleHelper.ProcessInstanceValue(dependencyObject, childIndex, instanceValues, dp, StyleHelper.UnsharedTemplateContentPropertyIndex, true /*apply*/);
// Create a Binding equivalent to the TemplateBindingExtension
Binding binding = new Binding();
binding.Mode = BindingMode.OneWay;
binding.RelativeSource = RelativeSource.TemplatedParent;
binding.Path = new PropertyPath(templateBindingExtension.Property);
binding.Converter = templateBindingExtension.Converter;
binding.ConverterParameter = templateBindingExtension.ConverterParameter;
value = binding;
}
else
{
Debug.Assert(false, "We do not have support for DynamicResource within unshared template content");
}
}
bool isMarkupExtension = value is MarkupExtension;
// Value needs to be valid for the DP, or Binding/MultiBinding/PriorityBinding/TemplateBinding.
if (!dp.IsValidValue(value))
{
if (!isMarkupExtension && !(value is DeferredReference))
{
throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name));
}
}
parentTemplateValues[dp] = value;
dependencyObject.ProvideSelfAsInheritanceContext( value, dp );
EffectiveValueEntry entry = new EffectiveValueEntry(dp);
entry.BaseValueSourceInternal = BaseValueSourceInternal.ParentTemplate;
entry.Value = value;
if (isMarkupExtension)
{
// entry will be updated to hold the value
StyleHelper.GetInstanceValue(
StyleHelper.TemplateDataField,
_templatedParent,
fo.FE,
fo.FCE,
childIndex,
dp,
StyleHelper.UnsharedTemplateContentPropertyIndex,
ref entry);
}
dependencyObject.UpdateEffectiveValue(
dependencyObject.LookupEntry(dp.GlobalIndex),
dp,
dp.GetMetadata(dependencyObject.DependencyObjectType),
new EffectiveValueEntry() /* oldEntry */,
ref entry,
false /* coerceWithDeferredReference */,
OperationType.Unknown);
}
// Since TemplateBinding can only be used in Templates this is overridden and
// specifically handled here.
internal override object GetExtensionValue(
IOptimizedMarkupExtension optimizedMarkupExtensionRecord,
string propertyName)
{
object valueObject = null;
short extensionTypeId = optimizedMarkupExtensionRecord.ExtensionTypeId;
if (extensionTypeId == (short)KnownElements.TemplateBindingExtension)
{
short memberId = optimizedMarkupExtensionRecord.ValueId;
DependencyProperty dp = MapTable.GetDependencyPropertyValueFromId(memberId);
if (dp != null)
{
valueObject = new TemplateBindingExtension(dp);
}
else
{
ThrowException(SRID.ParserCannotConvertPropertyValue,
propertyName,
typeof(TemplateBindingExtension).FullName);
}
}
else
{
valueObject = base.GetExtensionValue(optimizedMarkupExtensionRecord, propertyName);
}
return valueObject;
}
private DependencyObject _templatedParent;
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
/****************************************************************************\
*
* File: TemplateApplicationHelper.cs
*
* Copyright (C) 2005 by Microsoft Corporation. All rights reserved.
*
\***************************************************************************/
using MS.Internal;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Markup;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Controls;
using System.Collections.Specialized;
namespace System.Windows
{
//+---------------------------------------------------------------------------------------------
//
// Class TemplateApplicationHelper
//
// This class is a BamlRecordReader which is used to help instantiate a template.
// This BamlRecordReader is used to instantiate the unshareable content of the template,
// and we override SetDependencyValue here so that we can set values into
// the FE's special store for ParentTemplate values.
//
//+---------------------------------------------------------------------------------------------
internal class TemplateApplicationHelper : BamlRecordReader
{
internal TemplateApplicationHelper ( )
{
RootList = new ArrayList(1);
}
//
// Initialization is separate from the constructer so that it can be called
// repeatedly.
//
internal void Initialize( ParserContext parserContext, object templatedParent )
{
ParserContext = parserContext;
_templatedParent = (DependencyObject) templatedParent;
RootElement = null;
if( RootList != null )
{
RootList.Clear();
}
ContextStack.Clear();
ComponentConnector = null;
}
/***************************************************************************\
*
* TemplateBamlRecordReader.ReadDeferableContentStart
*
* Called when parsing the deferable content start element.
* When we have a ResourceDictionary inside template content,
* we need to retrieve the cached values buffer and supply it
* do the ResourceDictionary so that it can use it to
* RealizeDeferredContent.
*
\***************************************************************************/
internal override void ReadDeferableContentStart(
BamlDeferableContentStartRecord bamlRecord)
{
ResourceDictionary dictionary = GetDictionaryFromContext(CurrentContext, true /*toInsert*/) as ResourceDictionary;
if (dictionary != null)
{
// Read and create the keys and the static resource
// objects for this dictionary
ArrayList defKeyList;
List staticResourceValuesList;
BaseReadDeferableContentStart(bamlRecord, out defKeyList, out staticResourceValuesList);
// Supply the keys, static resources and values buffer to the
// dictionary so it can use it to realize deferred content.
dictionary.SetDeferableContent(bamlRecord.ValuesBuffer, ParserContext, RootElement, defKeyList, staticResourceValuesList);
}
}
//+------------------------------------------------------------------------------------------------------------
//
// SetDependencyValue (override)
//
// If a DP value is being set onto an FE/FCE that is being optimized as part of a template, put the
// value into the special ParentTemplate state.
//
//+-----------------------------------------------------------------------------------------------------------
internal override void SetDependencyValueCore(DependencyObject dependencyObject, DependencyProperty dp, object value )
{
FrameworkObject fo = new FrameworkObject(dependencyObject);
// If this isn't an FE that we're optimizing, defer to base.
//
// Similarly, if we don't have a templated parent, we're not optimizing, and defer to base
// (This happens when FrameworkTemplate.LoadContent() is called.)
if ((fo.TemplatedParent == null) || ( _templatedParent == null ))
{
base.SetDependencyValueCore( dependencyObject, dp, value );
return;
}
// For template content, we skip the automatic BaseUriProperty and the UidProperty
// (Implementation note: Doing this here because this is what we did with FEFs,
// and because automation gets confused if the Uid isn't unique in the whole tree).
if( dp == System.Windows.Navigation.BaseUriHelper.BaseUriProperty )
{
// We only skip the automatic BaseUri property. If it's set explicitely,
// that's passed through.
if (!fo.IsInitialized)
{
return;
}
}
else if (dp == UIElement.UidProperty)
{
return;
}
#if DEBUG
Debug.Assert(fo.TemplatedParent == _templatedParent);
#endif
// Set the value onto the FE/FCE.
HybridDictionary parentTemplateValues;
if (!fo.StoresParentTemplateValues)
{
parentTemplateValues = new HybridDictionary();
StyleHelper.ParentTemplateValuesField.SetValue(dependencyObject, parentTemplateValues);
fo.StoresParentTemplateValues = true;
}
else
{
parentTemplateValues = StyleHelper.ParentTemplateValuesField.GetValue(dependencyObject);
}
// Check if it is an expression
Expression expr;
int childIndex = fo.TemplateChildIndex;
if ((expr = value as Expression) != null)
{
BindingExpressionBase bindingExpr;
TemplateBindingExpression templateBindingExpr;
if ((bindingExpr = expr as BindingExpressionBase) != null)
{
// If this is a BindingExpression then we need to store the corresponding
// MarkupExtension into the per instance store for the unshared DP value.
// Allocate a slot for this unshared DP value in the per-instance store for MarkupExtensions
HybridDictionary instanceValues = StyleHelper.EnsureInstanceData(StyleHelper.TemplateDataField, _templatedParent, InstanceStyleData.InstanceValues);
StyleHelper.ProcessInstanceValue(dependencyObject, childIndex, instanceValues, dp, StyleHelper.UnsharedTemplateContentPropertyIndex, true /*apply*/);
value = bindingExpr.ParentBindingBase;
}
else if ((templateBindingExpr = expr as TemplateBindingExpression) != null)
{
// If this is a TemplateBindingExpression then we create an equivalent Binding
// MarkupExtension and store that in the per instance store for the unshared DP
// value. We use Binding here because it has all the wiring in place to handle
// change notifications through DependencySource and such.
TemplateBindingExtension templateBindingExtension = templateBindingExpr.TemplateBindingExtension;
// Allocate a slot for this unshared DP value in the per-instance store for MarkupExtensions
HybridDictionary instanceValues = StyleHelper.EnsureInstanceData(StyleHelper.TemplateDataField, _templatedParent, InstanceStyleData.InstanceValues);
StyleHelper.ProcessInstanceValue(dependencyObject, childIndex, instanceValues, dp, StyleHelper.UnsharedTemplateContentPropertyIndex, true /*apply*/);
// Create a Binding equivalent to the TemplateBindingExtension
Binding binding = new Binding();
binding.Mode = BindingMode.OneWay;
binding.RelativeSource = RelativeSource.TemplatedParent;
binding.Path = new PropertyPath(templateBindingExtension.Property);
binding.Converter = templateBindingExtension.Converter;
binding.ConverterParameter = templateBindingExtension.ConverterParameter;
value = binding;
}
else
{
Debug.Assert(false, "We do not have support for DynamicResource within unshared template content");
}
}
bool isMarkupExtension = value is MarkupExtension;
// Value needs to be valid for the DP, or Binding/MultiBinding/PriorityBinding/TemplateBinding.
if (!dp.IsValidValue(value))
{
if (!isMarkupExtension && !(value is DeferredReference))
{
throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name));
}
}
parentTemplateValues[dp] = value;
dependencyObject.ProvideSelfAsInheritanceContext( value, dp );
EffectiveValueEntry entry = new EffectiveValueEntry(dp);
entry.BaseValueSourceInternal = BaseValueSourceInternal.ParentTemplate;
entry.Value = value;
if (isMarkupExtension)
{
// entry will be updated to hold the value
StyleHelper.GetInstanceValue(
StyleHelper.TemplateDataField,
_templatedParent,
fo.FE,
fo.FCE,
childIndex,
dp,
StyleHelper.UnsharedTemplateContentPropertyIndex,
ref entry);
}
dependencyObject.UpdateEffectiveValue(
dependencyObject.LookupEntry(dp.GlobalIndex),
dp,
dp.GetMetadata(dependencyObject.DependencyObjectType),
new EffectiveValueEntry() /* oldEntry */,
ref entry,
false /* coerceWithDeferredReference */,
OperationType.Unknown);
}
// Since TemplateBinding can only be used in Templates this is overridden and
// specifically handled here.
internal override object GetExtensionValue(
IOptimizedMarkupExtension optimizedMarkupExtensionRecord,
string propertyName)
{
object valueObject = null;
short extensionTypeId = optimizedMarkupExtensionRecord.ExtensionTypeId;
if (extensionTypeId == (short)KnownElements.TemplateBindingExtension)
{
short memberId = optimizedMarkupExtensionRecord.ValueId;
DependencyProperty dp = MapTable.GetDependencyPropertyValueFromId(memberId);
if (dp != null)
{
valueObject = new TemplateBindingExtension(dp);
}
else
{
ThrowException(SRID.ParserCannotConvertPropertyValue,
propertyName,
typeof(TemplateBindingExtension).FullName);
}
}
else
{
valueObject = base.GetExtensionValue(optimizedMarkupExtensionRecord, propertyName);
}
return valueObject;
}
private DependencyObject _templatedParent;
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.