Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Data / ObjectRef.cs / 1305600 / ObjectRef.cs
//----------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
// Description: ObjectRef is a general way to name objects used in data binding
//
// See spec at http://avalon/connecteddata/Specs/Data%20Binding.mht
//
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
using MS.Internal;
using MS.Internal.Utility;
namespace MS.Internal.Data
{
#region ObjectRefArgs
// args to GetObject and GetDataObject
internal class ObjectRefArgs
{
internal bool IsTracing { get; set; }
internal bool ResolveNamesInTemplate { get; set; }
internal bool NameResolvedInOuterScope { get; set; }
}
#endregion ObjectRefArgs
#region ObjectRef
/// Abstract object reference.
internal abstract class ObjectRef
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
/// Constructor is protected - you can only create subclasses.
protected ObjectRef() {}
//------------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
/// Returns the referenced object.
/// Element defining context for the reference.
/// See ObjectRefArgs
internal virtual object GetObject(DependencyObject d, ObjectRefArgs args)
{
return null;
}
/// Returns the data object associated with the referenced object.
/// Often this is the same as the referenced object.
///
/// Element defining context for the reference.
/// See ObjectRefArgs
internal virtual object GetDataObject(DependencyObject d, ObjectRefArgs args)
{
return GetObject(d, args);
}
/// true if the ObjectRef really needs the tree context
internal bool TreeContextIsRequired(DependencyObject target)
{
return ProtectedTreeContextIsRequired(target);
}
/// true if the ObjectRef really needs the tree context
protected virtual bool ProtectedTreeContextIsRequired(DependencyObject target)
{
return false;
}
///
/// true if the ObjectRef uses the mentor of the target element,
/// rather than the target element itself.
///
internal bool UsesMentor
{
get { return ProtectedUsesMentor; }
}
///
/// true if the ObjectRef uses the mentor of the target element,
/// rather than the target element itself.
///
protected virtual bool ProtectedUsesMentor
{
get { return true; }
}
///
/// identify this ObjectRef to the user - used by extended tracing
///
internal abstract string Identify();
}
#endregion ObjectRef
#region ElementObjectRef
/// Object reference to a DependencyObject via its Name.
internal sealed class ElementObjectRef : ObjectRef
{
//------------------------------------------------------
//
// Constructors
//
//------------------------------------------------------
/// Constructor.
/// Name of the referenced Element.
/// name is a null reference
internal ElementObjectRef(string name)
{
if (name == null)
throw new ArgumentNullException("name");
_name = name.Trim();
}
//-----------------------------------------------------
//
// Public Methods
//
//------------------------------------------------------
/// Returns the referenced object.
/// Element defining context for the reference.
/// See ObjectRefArgs
internal override object GetObject(DependencyObject d, ObjectRefArgs args)
{
if (d == null)
throw new ArgumentNullException("d");
object o = null;
if (args.ResolveNamesInTemplate)
{
// look in container's template (if any) first
FrameworkElement fe = d as FrameworkElement;
if (fe != null && fe.TemplateInternal != null)
{
o = Helper.FindNameInTemplate(_name, d);
if (args.IsTracing)
{
TraceData.Trace(TraceEventType.Warning,
TraceData.ElementNameQueryTemplate(
_name,
TraceData.Identify(d)));
}
}
if (o == null)
{
args.NameResolvedInOuterScope = true;
}
}
FrameworkObject fo = new FrameworkObject(d);
while (o == null && fo.DO != null)
{
DependencyObject scopeOwner;
o = fo.FindName(_name, out scopeOwner);
// if the original element is a scope owner, supports IComponentConnector,
// and has a parent, don't use the result of FindName. The
// element is probably an instance of a Xaml-subclassed control;
// we want to resolve the name starting in the next outer scope.
// (bug 1669408)
// Also, if the element's NavigationService property is locally
// set, the element is the root of a navigation and should use the
// inner scope (bug 1765041)
if (d == scopeOwner && d is IComponentConnector &&
d.ReadLocalValue(System.Windows.Navigation.NavigationService.NavigationServiceProperty) == DependencyProperty.UnsetValue)
{
DependencyObject parent = LogicalTreeHelper.GetParent(d);
if (parent == null)
{
parent = Helper.FindMentor(d.InheritanceContext);
}
if (parent != null)
{
o = null;
fo.Reset(parent);
continue;
}
}
if (args.IsTracing)
{
TraceData.Trace(TraceEventType.Warning,
TraceData.ElementNameQuery(
_name,
TraceData.Identify(fo.DO)));
}
if (o == null)
{
args.NameResolvedInOuterScope = true;
// move to the next outer namescope.
// First try TemplatedParent of the scope owner.
FrameworkObject foScopeOwner = new FrameworkObject(scopeOwner);
DependencyObject dd = foScopeOwner.TemplatedParent;
// if that doesn't work, we could be at the top of
// generated content for an ItemsControl. If so, use
// the (visual) parent - a panel.
if (dd == null)
{
Panel panel = fo.FrameworkParent.DO as Panel;
if (panel != null && panel.IsItemsHost)
{
dd = panel;
}
}
// next, see if we're in a logical tree attached directly
// to a ContentPresenter. This is the m---- equivalent of
// having the ContentPresenter as the TemplatedParent.
if (dd == null && scopeOwner == null)
{
// go to the top of the logical subtree
DependencyObject parent;
for (dd = fo.DO;;)
{
parent = LogicalTreeHelper.GetParent(dd);
if (parent == null)
{
parent = Helper.FindMentor(dd.InheritanceContext);
}
if (parent == null)
break;
dd = parent;
}
// if it's attached to a ContentPresenter, move to the CP
ContentPresenter cp = VisualTreeHelper.IsVisualType(dd) ? VisualTreeHelper.GetParent(dd) as ContentPresenter : null;
dd = (cp != null && cp.TemplateInternal.CanBuildVisualTree) ? cp : null;
}
fo.Reset(dd);
}
}
if (o == null)
{
o = DependencyProperty.UnsetValue;
args.NameResolvedInOuterScope = false;
}
return o;
}
public override string ToString()
{
return String.Format(CultureInfo.InvariantCulture,
"ElementName={0}", _name);
}
internal override string Identify()
{
return "ElementName";
}
//-----------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
string _name;
}
#endregion ElementObjectRef
#region RelativeObjectRef
/// Object reference relative to the target element.
///
internal sealed class RelativeObjectRef : ObjectRef
{
//-----------------------------------------------------
//
// Constructors
//
//------------------------------------------------------
/// Constructor.
/// RelativeSource.
/// relativeSource is a null reference
internal RelativeObjectRef(RelativeSource relativeSource)
{
if (relativeSource == null)
throw new ArgumentNullException("relativeSource");
_relativeSource = relativeSource;
}
//-----------------------------------------------------
//
// Public Methods
//
//------------------------------------------------------
public override string ToString()
{
string s;
switch (_relativeSource.Mode)
{
case RelativeSourceMode.FindAncestor:
s = String.Format(CultureInfo.InvariantCulture,
"RelativeSource {0}, AncestorType='{1}', AncestorLevel='{2}'",
_relativeSource.Mode,
_relativeSource.AncestorType,
_relativeSource.AncestorLevel);
break;
default:
s = String.Format(CultureInfo.InvariantCulture,
"RelativeSource {0}", _relativeSource.Mode);
break;
}
return s;
}
/// Returns the referenced object.
/// Element defining context for the reference.
/// See ObjectRefArgs
/// d is a null reference
internal override object GetObject(DependencyObject d, ObjectRefArgs args)
{
return GetDataObjectImpl(d, args);
}
/// Returns the data object associated with the referenced object.
/// Often this is the same as the referenced object.
///
/// Element defining context for the reference.
/// See ObjectRefArgs
/// d is a null reference
internal override object GetDataObject(DependencyObject d, ObjectRefArgs args)
{
object o = GetDataObjectImpl(d, args);
DependencyObject el = o as DependencyObject;
if (el != null && ReturnsDataContext)
{
// for generated wrappers, use the ItemForContainer property instead
// of DataContext, since it's always set by the generator
o = el.GetValue(ItemContainerGenerator.ItemForItemContainerProperty);
if (o == null)
o = el.GetValue(FrameworkElement.DataContextProperty);
}
return o;
}
private object GetDataObjectImpl(DependencyObject d, ObjectRefArgs args)
{
if (d == null)
return null;
switch (_relativeSource.Mode)
{
case RelativeSourceMode.Self:
break; // nothing to do
case RelativeSourceMode.TemplatedParent:
d = Helper.GetTemplatedParent(d);
break;
case RelativeSourceMode.PreviousData:
return GetPreviousData(d);
case RelativeSourceMode.FindAncestor:
d = FindAncestorOfType(_relativeSource.AncestorType, _relativeSource.AncestorLevel, d, args.IsTracing);
if (d == null)
{
return DependencyProperty.UnsetValue; // we fell off the tree
}
break;
default:
return null;
}
if (args.IsTracing)
{
TraceData.Trace(TraceEventType.Warning,
TraceData.RelativeSource(
_relativeSource.Mode,
TraceData.Identify(d)));
}
return d;
}
internal bool ReturnsDataContext
{
get { return (_relativeSource.Mode == RelativeSourceMode.PreviousData); }
}
/// true if the ObjectRef really needs the tree context
protected override bool ProtectedTreeContextIsRequired(DependencyObject target)
{
return ( (_relativeSource.Mode == RelativeSourceMode.FindAncestor
|| (_relativeSource.Mode == RelativeSourceMode.PreviousData)));
}
protected override bool ProtectedUsesMentor
{
get
{
switch (_relativeSource.Mode)
{
case RelativeSourceMode.TemplatedParent:
case RelativeSourceMode.PreviousData:
return true;
default:
return false;
}
}
}
internal override string Identify()
{
return String.Format(System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS,
"RelativeSource ({0})", _relativeSource.Mode);
}
//------------------------------------------------------
//
// Private Method
//
//-----------------------------------------------------
private object GetPreviousData(DependencyObject d)
{
// move up to the next containing DataContext scope
for (; d != null; d = FrameworkElement.GetFrameworkParent(d))
{
if (BindingExpression.HasLocalDataContext(d))
{
// special case: if the element is a ContentPresenter
// whose templated parent is a ContentControl or
// HeaderedItemsControl, and both have the same
// DataContext, we'll use the parent instead of the
// ContentPresenter. In this case, the DataContext
// of the CP is set by various forwarding rules, and
// shouldn't count as a new scope.
// Similarly, do the same for a FE whose parent
// is a GridViewRowPresenter; this enables Previous bindings
// inside ListView.
FrameworkElement parent, child;
ContentPresenter cp;
if ((cp = d as ContentPresenter) != null)
{
child = cp;
parent = cp.TemplatedParent as FrameworkElement;
if (!(parent is ContentControl || parent is HeaderedItemsControl))
{
parent = cp.Parent as System.Windows.Controls.Primitives.GridViewRowPresenterBase;
}
}
else
{
child = d as FrameworkElement;
parent = ((child != null) ? child.Parent : null) as System.Windows.Controls.Primitives.GridViewRowPresenterBase;
}
if (child != null && parent != null &&
Object.Equals(child.DataContext, parent.DataContext))
{
d = parent;
if (!BindingExpression.HasLocalDataContext(parent))
{
continue;
}
}
break;
}
}
if (d == null)
return DependencyProperty.UnsetValue; // we fell off the tree
// this only makes sense within generated content. If this
// is the case, then d is now the wrapper element, its visual
// parent is the layout element, and the layout's ItemsOwner
// is the govening ItemsControl.
Visual v = d as Visual;
DependencyObject layout = (v != null) ? VisualTreeHelper.GetParent(v) : null;
ItemsControl ic = ItemsControl.GetItemsOwner(layout);
if (ic == null)
{
if (TraceData.IsEnabled)
TraceData.Trace(TraceEventType.Error, TraceData.RefPreviousNotInContext);
return null;
}
// now look up the wrapper's previous sibling within the
// layout's children collection
Visual v2 = layout as Visual;
int count = (v2 != null) ? v2.InternalVisualChildrenCount : 0;
int j = -1;
Visual prevChild = null; //child at j-1th index
if (count != 0)
{
j = IndexOf(v2, v, out prevChild);
}
if (j > 0)
{
d = prevChild;
}
else
{
d = null;
if ((j < 0) && TraceData.IsEnabled)
TraceData.Trace(TraceEventType.Error, TraceData.RefNoWrapperInChildren);
}
return d;
}
private DependencyObject FindAncestorOfType(Type type, int level, DependencyObject d, bool isTracing)
{
if (type == null)
{
if (TraceData.IsEnabled)
TraceData.Trace(TraceEventType.Error, TraceData.RefAncestorTypeNotSpecified);
return null;
}
if (level < 1)
{
if (TraceData.IsEnabled)
TraceData.Trace(TraceEventType.Error, TraceData.RefAncestorLevelInvalid);
return null;
}
// initialize search to start at the parent of the given DO
FrameworkObject fo = new FrameworkObject(d);
fo.Reset(fo.GetPreferVisualParent(true).DO);
while (fo.DO != null)
{
if (isTracing)
{
TraceData.Trace(TraceEventType.Warning,
TraceData.AncestorLookup(
type.Name,
TraceData.Identify(fo.DO)));
}
if (type.IsInstanceOfType(fo.DO)) // found it!
{
if (--level <= 0)
break;
}
fo.Reset(fo.PreferVisualParent.DO);
}
return fo.DO;
}
private int IndexOf(Visual parent, Visual child, out Visual prevChild)
{
Visual temp;
bool foundIndex = false;
prevChild = null;
int count = parent.InternalVisualChildrenCount;
int i;
for(i = 0; i < count; i++)
{
temp = parent.InternalGetVisualChild(i);
if(child == temp)
{
foundIndex = true;
break;
}
prevChild = temp;
}
if (foundIndex) return i;
else return -1;
}
//------------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
RelativeSource _relativeSource;
}
#endregion RelativeObjectRef
#region ExplicitObjectRef
/// Explicit object reference.
internal sealed class ExplicitObjectRef: ObjectRef
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
/// Constructor.
internal ExplicitObjectRef(object o)
{
if (o is DependencyObject)
_element = new WeakReference(o);
else
_object = o;
}
//------------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
/// Returns the referenced object.
/// Element defining context for the reference.
/// See ObjectRefArgs
internal override object GetObject(DependencyObject d, ObjectRefArgs args)
{
return (_element != null) ? _element.Target : _object;
}
///
/// true if the ObjectRef uses the mentor of the target element,
/// rather than the target element itself.
///
protected override bool ProtectedUsesMentor
{
get { return false; }
}
internal override string Identify()
{
return "Source";
}
//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
object _object;
WeakReference _element; // to DependencyObject (bug 986435)
}
#endregion ExplicitObjectRef
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
// Description: ObjectRef is a general way to name objects used in data binding
//
// See spec at http://avalon/connecteddata/Specs/Data%20Binding.mht
//
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
using MS.Internal;
using MS.Internal.Utility;
namespace MS.Internal.Data
{
#region ObjectRefArgs
// args to GetObject and GetDataObject
internal class ObjectRefArgs
{
internal bool IsTracing { get; set; }
internal bool ResolveNamesInTemplate { get; set; }
internal bool NameResolvedInOuterScope { get; set; }
}
#endregion ObjectRefArgs
#region ObjectRef
/// Abstract object reference.
internal abstract class ObjectRef
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
/// Constructor is protected - you can only create subclasses.
protected ObjectRef() {}
//------------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
/// Returns the referenced object.
/// Element defining context for the reference.
/// See ObjectRefArgs
internal virtual object GetObject(DependencyObject d, ObjectRefArgs args)
{
return null;
}
/// Returns the data object associated with the referenced object.
/// Often this is the same as the referenced object.
///
/// Element defining context for the reference.
/// See ObjectRefArgs
internal virtual object GetDataObject(DependencyObject d, ObjectRefArgs args)
{
return GetObject(d, args);
}
/// true if the ObjectRef really needs the tree context
internal bool TreeContextIsRequired(DependencyObject target)
{
return ProtectedTreeContextIsRequired(target);
}
/// true if the ObjectRef really needs the tree context
protected virtual bool ProtectedTreeContextIsRequired(DependencyObject target)
{
return false;
}
///
/// true if the ObjectRef uses the mentor of the target element,
/// rather than the target element itself.
///
internal bool UsesMentor
{
get { return ProtectedUsesMentor; }
}
///
/// true if the ObjectRef uses the mentor of the target element,
/// rather than the target element itself.
///
protected virtual bool ProtectedUsesMentor
{
get { return true; }
}
///
/// identify this ObjectRef to the user - used by extended tracing
///
internal abstract string Identify();
}
#endregion ObjectRef
#region ElementObjectRef
/// Object reference to a DependencyObject via its Name.
internal sealed class ElementObjectRef : ObjectRef
{
//------------------------------------------------------
//
// Constructors
//
//------------------------------------------------------
/// Constructor.
/// Name of the referenced Element.
/// name is a null reference
internal ElementObjectRef(string name)
{
if (name == null)
throw new ArgumentNullException("name");
_name = name.Trim();
}
//-----------------------------------------------------
//
// Public Methods
//
//------------------------------------------------------
/// Returns the referenced object.
/// Element defining context for the reference.
/// See ObjectRefArgs
internal override object GetObject(DependencyObject d, ObjectRefArgs args)
{
if (d == null)
throw new ArgumentNullException("d");
object o = null;
if (args.ResolveNamesInTemplate)
{
// look in container's template (if any) first
FrameworkElement fe = d as FrameworkElement;
if (fe != null && fe.TemplateInternal != null)
{
o = Helper.FindNameInTemplate(_name, d);
if (args.IsTracing)
{
TraceData.Trace(TraceEventType.Warning,
TraceData.ElementNameQueryTemplate(
_name,
TraceData.Identify(d)));
}
}
if (o == null)
{
args.NameResolvedInOuterScope = true;
}
}
FrameworkObject fo = new FrameworkObject(d);
while (o == null && fo.DO != null)
{
DependencyObject scopeOwner;
o = fo.FindName(_name, out scopeOwner);
// if the original element is a scope owner, supports IComponentConnector,
// and has a parent, don't use the result of FindName. The
// element is probably an instance of a Xaml-subclassed control;
// we want to resolve the name starting in the next outer scope.
// (bug 1669408)
// Also, if the element's NavigationService property is locally
// set, the element is the root of a navigation and should use the
// inner scope (bug 1765041)
if (d == scopeOwner && d is IComponentConnector &&
d.ReadLocalValue(System.Windows.Navigation.NavigationService.NavigationServiceProperty) == DependencyProperty.UnsetValue)
{
DependencyObject parent = LogicalTreeHelper.GetParent(d);
if (parent == null)
{
parent = Helper.FindMentor(d.InheritanceContext);
}
if (parent != null)
{
o = null;
fo.Reset(parent);
continue;
}
}
if (args.IsTracing)
{
TraceData.Trace(TraceEventType.Warning,
TraceData.ElementNameQuery(
_name,
TraceData.Identify(fo.DO)));
}
if (o == null)
{
args.NameResolvedInOuterScope = true;
// move to the next outer namescope.
// First try TemplatedParent of the scope owner.
FrameworkObject foScopeOwner = new FrameworkObject(scopeOwner);
DependencyObject dd = foScopeOwner.TemplatedParent;
// if that doesn't work, we could be at the top of
// generated content for an ItemsControl. If so, use
// the (visual) parent - a panel.
if (dd == null)
{
Panel panel = fo.FrameworkParent.DO as Panel;
if (panel != null && panel.IsItemsHost)
{
dd = panel;
}
}
// next, see if we're in a logical tree attached directly
// to a ContentPresenter. This is the m---- equivalent of
// having the ContentPresenter as the TemplatedParent.
if (dd == null && scopeOwner == null)
{
// go to the top of the logical subtree
DependencyObject parent;
for (dd = fo.DO;;)
{
parent = LogicalTreeHelper.GetParent(dd);
if (parent == null)
{
parent = Helper.FindMentor(dd.InheritanceContext);
}
if (parent == null)
break;
dd = parent;
}
// if it's attached to a ContentPresenter, move to the CP
ContentPresenter cp = VisualTreeHelper.IsVisualType(dd) ? VisualTreeHelper.GetParent(dd) as ContentPresenter : null;
dd = (cp != null && cp.TemplateInternal.CanBuildVisualTree) ? cp : null;
}
fo.Reset(dd);
}
}
if (o == null)
{
o = DependencyProperty.UnsetValue;
args.NameResolvedInOuterScope = false;
}
return o;
}
public override string ToString()
{
return String.Format(CultureInfo.InvariantCulture,
"ElementName={0}", _name);
}
internal override string Identify()
{
return "ElementName";
}
//-----------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
string _name;
}
#endregion ElementObjectRef
#region RelativeObjectRef
/// Object reference relative to the target element.
///
internal sealed class RelativeObjectRef : ObjectRef
{
//-----------------------------------------------------
//
// Constructors
//
//------------------------------------------------------
/// Constructor.
/// RelativeSource.
/// relativeSource is a null reference
internal RelativeObjectRef(RelativeSource relativeSource)
{
if (relativeSource == null)
throw new ArgumentNullException("relativeSource");
_relativeSource = relativeSource;
}
//-----------------------------------------------------
//
// Public Methods
//
//------------------------------------------------------
public override string ToString()
{
string s;
switch (_relativeSource.Mode)
{
case RelativeSourceMode.FindAncestor:
s = String.Format(CultureInfo.InvariantCulture,
"RelativeSource {0}, AncestorType='{1}', AncestorLevel='{2}'",
_relativeSource.Mode,
_relativeSource.AncestorType,
_relativeSource.AncestorLevel);
break;
default:
s = String.Format(CultureInfo.InvariantCulture,
"RelativeSource {0}", _relativeSource.Mode);
break;
}
return s;
}
/// Returns the referenced object.
/// Element defining context for the reference.
/// See ObjectRefArgs
/// d is a null reference
internal override object GetObject(DependencyObject d, ObjectRefArgs args)
{
return GetDataObjectImpl(d, args);
}
/// Returns the data object associated with the referenced object.
/// Often this is the same as the referenced object.
///
/// Element defining context for the reference.
/// See ObjectRefArgs
/// d is a null reference
internal override object GetDataObject(DependencyObject d, ObjectRefArgs args)
{
object o = GetDataObjectImpl(d, args);
DependencyObject el = o as DependencyObject;
if (el != null && ReturnsDataContext)
{
// for generated wrappers, use the ItemForContainer property instead
// of DataContext, since it's always set by the generator
o = el.GetValue(ItemContainerGenerator.ItemForItemContainerProperty);
if (o == null)
o = el.GetValue(FrameworkElement.DataContextProperty);
}
return o;
}
private object GetDataObjectImpl(DependencyObject d, ObjectRefArgs args)
{
if (d == null)
return null;
switch (_relativeSource.Mode)
{
case RelativeSourceMode.Self:
break; // nothing to do
case RelativeSourceMode.TemplatedParent:
d = Helper.GetTemplatedParent(d);
break;
case RelativeSourceMode.PreviousData:
return GetPreviousData(d);
case RelativeSourceMode.FindAncestor:
d = FindAncestorOfType(_relativeSource.AncestorType, _relativeSource.AncestorLevel, d, args.IsTracing);
if (d == null)
{
return DependencyProperty.UnsetValue; // we fell off the tree
}
break;
default:
return null;
}
if (args.IsTracing)
{
TraceData.Trace(TraceEventType.Warning,
TraceData.RelativeSource(
_relativeSource.Mode,
TraceData.Identify(d)));
}
return d;
}
internal bool ReturnsDataContext
{
get { return (_relativeSource.Mode == RelativeSourceMode.PreviousData); }
}
/// true if the ObjectRef really needs the tree context
protected override bool ProtectedTreeContextIsRequired(DependencyObject target)
{
return ( (_relativeSource.Mode == RelativeSourceMode.FindAncestor
|| (_relativeSource.Mode == RelativeSourceMode.PreviousData)));
}
protected override bool ProtectedUsesMentor
{
get
{
switch (_relativeSource.Mode)
{
case RelativeSourceMode.TemplatedParent:
case RelativeSourceMode.PreviousData:
return true;
default:
return false;
}
}
}
internal override string Identify()
{
return String.Format(System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS,
"RelativeSource ({0})", _relativeSource.Mode);
}
//------------------------------------------------------
//
// Private Method
//
//-----------------------------------------------------
private object GetPreviousData(DependencyObject d)
{
// move up to the next containing DataContext scope
for (; d != null; d = FrameworkElement.GetFrameworkParent(d))
{
if (BindingExpression.HasLocalDataContext(d))
{
// special case: if the element is a ContentPresenter
// whose templated parent is a ContentControl or
// HeaderedItemsControl, and both have the same
// DataContext, we'll use the parent instead of the
// ContentPresenter. In this case, the DataContext
// of the CP is set by various forwarding rules, and
// shouldn't count as a new scope.
// Similarly, do the same for a FE whose parent
// is a GridViewRowPresenter; this enables Previous bindings
// inside ListView.
FrameworkElement parent, child;
ContentPresenter cp;
if ((cp = d as ContentPresenter) != null)
{
child = cp;
parent = cp.TemplatedParent as FrameworkElement;
if (!(parent is ContentControl || parent is HeaderedItemsControl))
{
parent = cp.Parent as System.Windows.Controls.Primitives.GridViewRowPresenterBase;
}
}
else
{
child = d as FrameworkElement;
parent = ((child != null) ? child.Parent : null) as System.Windows.Controls.Primitives.GridViewRowPresenterBase;
}
if (child != null && parent != null &&
Object.Equals(child.DataContext, parent.DataContext))
{
d = parent;
if (!BindingExpression.HasLocalDataContext(parent))
{
continue;
}
}
break;
}
}
if (d == null)
return DependencyProperty.UnsetValue; // we fell off the tree
// this only makes sense within generated content. If this
// is the case, then d is now the wrapper element, its visual
// parent is the layout element, and the layout's ItemsOwner
// is the govening ItemsControl.
Visual v = d as Visual;
DependencyObject layout = (v != null) ? VisualTreeHelper.GetParent(v) : null;
ItemsControl ic = ItemsControl.GetItemsOwner(layout);
if (ic == null)
{
if (TraceData.IsEnabled)
TraceData.Trace(TraceEventType.Error, TraceData.RefPreviousNotInContext);
return null;
}
// now look up the wrapper's previous sibling within the
// layout's children collection
Visual v2 = layout as Visual;
int count = (v2 != null) ? v2.InternalVisualChildrenCount : 0;
int j = -1;
Visual prevChild = null; //child at j-1th index
if (count != 0)
{
j = IndexOf(v2, v, out prevChild);
}
if (j > 0)
{
d = prevChild;
}
else
{
d = null;
if ((j < 0) && TraceData.IsEnabled)
TraceData.Trace(TraceEventType.Error, TraceData.RefNoWrapperInChildren);
}
return d;
}
private DependencyObject FindAncestorOfType(Type type, int level, DependencyObject d, bool isTracing)
{
if (type == null)
{
if (TraceData.IsEnabled)
TraceData.Trace(TraceEventType.Error, TraceData.RefAncestorTypeNotSpecified);
return null;
}
if (level < 1)
{
if (TraceData.IsEnabled)
TraceData.Trace(TraceEventType.Error, TraceData.RefAncestorLevelInvalid);
return null;
}
// initialize search to start at the parent of the given DO
FrameworkObject fo = new FrameworkObject(d);
fo.Reset(fo.GetPreferVisualParent(true).DO);
while (fo.DO != null)
{
if (isTracing)
{
TraceData.Trace(TraceEventType.Warning,
TraceData.AncestorLookup(
type.Name,
TraceData.Identify(fo.DO)));
}
if (type.IsInstanceOfType(fo.DO)) // found it!
{
if (--level <= 0)
break;
}
fo.Reset(fo.PreferVisualParent.DO);
}
return fo.DO;
}
private int IndexOf(Visual parent, Visual child, out Visual prevChild)
{
Visual temp;
bool foundIndex = false;
prevChild = null;
int count = parent.InternalVisualChildrenCount;
int i;
for(i = 0; i < count; i++)
{
temp = parent.InternalGetVisualChild(i);
if(child == temp)
{
foundIndex = true;
break;
}
prevChild = temp;
}
if (foundIndex) return i;
else return -1;
}
//------------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
RelativeSource _relativeSource;
}
#endregion RelativeObjectRef
#region ExplicitObjectRef
/// Explicit object reference.
internal sealed class ExplicitObjectRef: ObjectRef
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
/// Constructor.
internal ExplicitObjectRef(object o)
{
if (o is DependencyObject)
_element = new WeakReference(o);
else
_object = o;
}
//------------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
/// Returns the referenced object.
/// Element defining context for the reference.
/// See ObjectRefArgs
internal override object GetObject(DependencyObject d, ObjectRefArgs args)
{
return (_element != null) ? _element.Target : _object;
}
///
/// true if the ObjectRef uses the mentor of the target element,
/// rather than the target element itself.
///
protected override bool ProtectedUsesMentor
{
get { return false; }
}
internal override string Identify()
{
return "Source";
}
//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
object _object;
WeakReference _element; // to DependencyObject (bug 986435)
}
#endregion ExplicitObjectRef
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TextServicesManager.cs
- Completion.cs
- ImagingCache.cs
- Options.cs
- SingleKeyFrameCollection.cs
- ObjectStateManager.cs
- PublisherMembershipCondition.cs
- XXXInfos.cs
- IgnoreSection.cs
- SchemaType.cs
- ILGen.cs
- QuaternionConverter.cs
- CustomErrorCollection.cs
- ReflectionUtil.cs
- IsolatedStoragePermission.cs
- MethodBuilder.cs
- CreateUserWizardDesigner.cs
- smtpconnection.cs
- AspNetRouteServiceHttpHandler.cs
- EditorPartChrome.cs
- NegationPusher.cs
- FixUp.cs
- User.cs
- HttpContextBase.cs
- TransformerInfoCollection.cs
- Substitution.cs
- Misc.cs
- GridViewEditEventArgs.cs
- SecurityTokenParameters.cs
- LinqDataSourceHelper.cs
- _ChunkParse.cs
- OutputCacheProfile.cs
- CodeDOMProvider.cs
- TdsEnums.cs
- ResXFileRef.cs
- XmlSchemaType.cs
- DataControlFieldCollection.cs
- XmlSchemaDocumentation.cs
- BmpBitmapDecoder.cs
- UInt16.cs
- ResourcePropertyMemberCodeDomSerializer.cs
- Clock.cs
- CodeTypeMemberCollection.cs
- SolidColorBrush.cs
- SamlAdvice.cs
- CssStyleCollection.cs
- BoundingRectTracker.cs
- EntityClassGenerator.cs
- TimelineGroup.cs
- Environment.cs
- ClrPerspective.cs
- EndOfStreamException.cs
- ObjectDataSourceDisposingEventArgs.cs
- CodeTypeReferenceExpression.cs
- HttpResponse.cs
- DataGridViewHeaderCell.cs
- ListViewSortEventArgs.cs
- GB18030Encoding.cs
- DataSourceXmlSubItemAttribute.cs
- DataGridViewTopRowAccessibleObject.cs
- ActionNotSupportedException.cs
- QuotedPrintableStream.cs
- ServiceContractAttribute.cs
- OutputScopeManager.cs
- ObjectHandle.cs
- ScalarType.cs
- StyleSheetRefUrlEditor.cs
- ResetableIterator.cs
- RadioButtonAutomationPeer.cs
- WmpBitmapEncoder.cs
- DesignerTransactionCloseEvent.cs
- Point3DCollectionConverter.cs
- InstanceDataCollection.cs
- RightNameExpirationInfoPair.cs
- JsonReaderWriterFactory.cs
- HtmlTableCell.cs
- GridProviderWrapper.cs
- QuaternionAnimationBase.cs
- ClientFormsAuthenticationCredentials.cs
- TextBox.cs
- XhtmlConformanceSection.cs
- ProgressiveCrcCalculatingStream.cs
- DeferredReference.cs
- ComplexType.cs
- NetSectionGroup.cs
- ModelUtilities.cs
- ExpressionBinding.cs
- XpsResource.cs
- FileDialog.cs
- DependencySource.cs
- PenLineCapValidation.cs
- PrinterResolution.cs
- DescendentsWalkerBase.cs
- DesignerActionVerbItem.cs
- DebugView.cs
- QuadraticBezierSegment.cs
- ClientUrlResolverWrapper.cs
- ListChangedEventArgs.cs
- IgnoreDeviceFilterElement.cs
- HitTestParameters3D.cs