Hello,
I'm trying to use an aggegate object which contains two objects and using the ICustomTypeDescriptor I would like to expose all the properties from both containined objects in a single aggegated object. So, I've implemented this aggregated object as follow :
public class Aggregated : ICustomTypeDescriptor
{
readonly Object _main;
readonly Object _extended;
public Aggregated(Object main, Object extended)
{
_main = main;
_extended = extended;
}
public Object Main
{
get { return _main; }
}
public Object Extended
{
get { return _extended; }
}
#region ICustomTypeDescriptor implementation
AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
return TypeDescriptor.GetAttributes(Main, true);
}
string ICustomTypeDescriptor.GetClassName()
{
return TypeDescriptor.GetClassName(Main, true);
}
string ICustomTypeDescriptor.GetComponentName()
{
return TypeDescriptor.GetComponentName(Main, true);
}
TypeConverter ICustomTypeDescriptor.GetConverter()
{
return TypeDescriptor.GetConverter(Main, true);
}
EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(Main, true);
}
PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(Main, true);
}
object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(Main, editorBaseType, true);
}
EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(Main, attributes, true);
}
EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
return TypeDescriptor.GetEvents(Main, true);
}
PropertyDescriptorCollection propsAttribute1;
PropertyDescriptorCollection propsAttribute2;
PropertyDescriptorCollection retAttributes;
PropertyDescriptorCollection props1;
PropertyDescriptorCollection props2;
PropertyDescriptorCollection ret;
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
if (retAttributes != null)
return retAttributes;
propsAttribute1 = TypeDescriptor.GetProperties(Main, attributes, true);
propsAttribute2 = TypeDescriptor.GetProperties(Extended, attributes, true);
retAttributes = new PropertyDescriptorCollection(null);
foreach (PropertyDescriptor prop in propsAttribute1)
retAttributes.Add(prop);
foreach (PropertyDescriptor prop in propsAttribute2)
retAttributes.Add(prop);
return retAttributes;
}
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
if (ret != null)
return ret;
props1 = TypeDescriptor.GetProperties(Main, true);
props2 = TypeDescriptor.GetProperties(Extended, true);
ret = new PropertyDescriptorCollection(null);
foreach (PropertyDescriptor prop in props1)
ret.Add(prop);
foreach (PropertyDescriptor prop in props2)
ret.Add(prop);
return ret;
}
object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{
if (props1.Contains(pd) || propsAttribute1.Contains(pd))
return Main;
if (props2.Contains(pd) || propsAttribute2.Contains(pd))
return Extended;
return Main;
}
Using this aggregate class I get the following exception :
Unable to cast object of type 'PropertyControl.ComponentService.Aggregated' to type 'System.Windows.DependencyObject'.
call stack :
at MS.Internal.ComponentModel.DependencyObjectPropertyDescriptor.FromObj(Object value)
at MS.Internal.ComponentModel.DependencyObjectPropertyDescriptor.GetValue(Object component)
at #ZC.#0C.getValue()
at Mindscape.WpfElements.PropertyEditing.Many1.GetValue(T& value, Boolean& isConsistent)
at Mindscape.WpfElements.PropertyEditing.Many
1.#SV()
at Mindscape.WpfElements.PropertyEditing.Many.#LV(Type type, IList`1 properties, #pD descriptor)
at Mindscape.WpfElements.PropertyEditing.MultipleObjectWrapper.GetValue(#pD property)
at #ZC.#pD.GetValue(Object component)
at #ZC.#Vl.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at Mindscape.WpfElements.PropertyEditing.PropertyNode.getValue()
at Mindscape.WpfElements.PropertyEditing.BuiltInEditor.#3(Node node, Boolean editable, Boolean& allowExpand)
at Mindscape.WpfElements.PropertyEditing.BuiltInEditor.GetEditSettings(Node node)
at Mindscape.WpfElements.PropertyEditing.BuiltInEditor.CanEdit(Node node)
at Mindscape.WpfElements.PropertyEditing.ObjectWrappingEditor.BuildTemplate(Node node)
at Mindscape.WpfElements.PropertyEditing.EditorSelector.SelectTemplate(Object item, DependencyObject container)
at System.Windows.Controls.ContentPresenter.ChooseTemplate()
at System.Windows.Controls.ContentPresenter.EnsureTemplate()
at System.Windows.Controls.ContentPresenter.OnPreApplyTemplate()
at System.Windows.FrameworkElement.ApplyTemplate()
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run()
at UFSolution.Startup.Main(String[] args) in e:\Documents\Visual Studio 2010\Projects\UFSolution\UFSolution\Startup.cs:line 166
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
the Main contained object is a WPF FrameworkElement, but the implementation for ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) is never called for the WPF frameworkElement properties.
Can you please check if there is a workaround ?
thanks