icsharpcode / WpfDesigner

The WPF Designer from SharpDevelop
MIT License
949 stars 251 forks source link

NullReferenceException in ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.TimeSpanEditor.NumberEditor_DataContextChanged #57

Closed JoshWobbles closed 5 years ago

JoshWobbles commented 5 years ago

when using a MediaElement, I get the following exception whenever I try to select the control in the design view.

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. at ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.TimeSpanEditor.NumberEditor_DataContextChanged(Object sender, DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.RaiseDependencyPropertyChanged(EventPrivateKey key, DependencyPropertyChangedEventArgs args) at System.Windows.FrameworkElement.OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.TreeWalkHelper.InvalidateTreeDependentProperty(TreeChangeInfo info, DependencyObject d, FrameworkObject& fo, DependencyProperty dp, FrameworkPropertyMetadata fMetadata, Style selfStyle, Style selfThemeStyle, ChildRecord& childRecord, Boolean isChildRecordValid, Boolean hasStyleChanged, Boolean isSelfInheritanceParent, Boolean wasSelfInheritanceParent) at System.Windows.TreeWalkHelper.InvalidateTreeDependentProperties(TreeChangeInfo info, FrameworkElement fe, FrameworkContentElement fce, Style selfStyle, Style selfThemeStyle, ChildRecord& childRecord, Boolean isChildRecordValid, Boolean hasStyleChanged, Boolean isSelfInheritanceParent, Boolean wasSelfInheritanceParent) at System.Windows.FrameworkElement.InvalidateTreeDependentProperties(TreeChangeInfo parentTreeState, Boolean isSelfInheritanceParent, Boolean wasSelfInheritanceParent) at System.Windows.FrameworkElement.OnAncestorChangedInternal(TreeChangeInfo parentTreeState) at System.Windows.TreeWalkHelper.OnAncestorChanged(DependencyObject d, TreeChangeInfo info, Boolean visitedViaVisualTree) at System.Windows.DescendentsWalker1.StartWalk(DependencyObject startNode, Boolean skipStartNode) at MS.Internal.PrePostDescendentsWalker1.StartWalk(DependencyObject startNode, Boolean skipStartNode) at System.Windows.TreeWalkHelper.InvalidateOnTreeChange(FrameworkElement fe, FrameworkContentElement fce, DependencyObject parent, Boolean isAddOperation) at System.Windows.FrameworkElement.OnVisualParentChanged(DependencyObject oldParent) at System.Windows.Media.Visual.FireOnVisualParentChanged(DependencyObject oldParent) at System.Windows.Media.Visual.AddVisualChild(Visual child) at System.Windows.FrameworkElement.set_TemplateChild(UIElement value) at System.Windows.Controls.ContentPresenter.UseContentTemplate.BuildVisualTree(FrameworkElement container) at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate) at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField1 templateDataField, FrameworkElement container) at System.Windows.FrameworkElement.ApplyTemplate() at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Border.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.DockPanel.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Border.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.StackPanel.StackMeasureHelper(IStackMeasure measureElement, IStackMeasureScrollData scrollData, Size constraint) at System.Windows.Controls.StackPanel.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double& computedUniformOrAverageContainerSize, Double& computedUniformOrAverageContainerPixelSize, Boolean& computedAreContainersUniformlySized, Boolean& hasAnyContainerSpanChanged, IList& items, Object& item, IList& children, Int32& childIndex, Boolean& visualOrderChanged, Boolean& isHorizontal, Size& childConstraint, Rect& viewport, VirtualizationCacheLength& cacheSize, VirtualizationCacheLengthUnit& cacheUnit, Boolean& foundFirstItemInViewport, Double& firstItemInViewportOffset, Size& stackPixelSize, Size& stackPixelSizeInViewport, Size& stackPixelSizeInCacheBeforeViewport, Size& stackPixelSizeInCacheAfterViewport, Size& stackLogicalSize, Size& stackLogicalSizeInViewport, Size& stackLogicalSizeInCacheBeforeViewport, Size& stackLogicalSizeInCacheAfterViewport, Boolean& mustDisableVirtualization, Boolean isBeforeFirstItem, Boolean isAfterFirstItem, Boolean isAfterLastItem, Boolean skipActualMeasure, Boolean skipGeneration, Boolean& hasBringIntoViewContainerBeenMeasured, Boolean& hasVirtualizingChildren) at System.Windows.Controls.VirtualizingStackPanel.MeasureOverrideImpl(Size constraint, Nullable1& lastPageSafeOffset, List1& previouslyMeasuredOffsets, Nullable1& lastPagePixelSize, Boolean remeasure) at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) at System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Border.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Control.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.DockPanel.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.Control.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double& computedUniformOrAverageContainerSize, Double& computedUniformOrAverageContainerPixelSize, Boolean& computedAreContainersUniformlySized, Boolean& hasAnyContainerSpanChanged, IList& items, Object& item, IList& children, Int32& childIndex, Boolean& visualOrderChanged, Boolean& isHorizontal, Size& childConstraint, Rect& viewport, VirtualizationCacheLength& cacheSize, VirtualizationCacheLengthUnit& cacheUnit, Boolean& foundFirstItemInViewport, Double& firstItemInViewportOffset, Size& stackPixelSize, Size& stackPixelSizeInViewport, Size& stackPixelSizeInCacheBeforeViewport, Size& stackPixelSizeInCacheAfterViewport, Size& stackLogicalSize, Size& stackLogicalSizeInViewport, Size& stackLogicalSizeInCacheBeforeViewport, Size& stackLogicalSizeInCacheAfterViewport, Boolean& mustDisableVirtualization, Boolean isBeforeFirstItem, Boolean isAfterFirstItem, Boolean isAfterLastItem, Boolean skipActualMeasure, Boolean skipGeneration, Boolean& hasBringIntoViewContainerBeenMeasured, Boolean& hasVirtualizingChildren) at System.Windows.Controls.VirtualizingStackPanel.MeasureOverrideImpl(Size constraint, Nullable1& lastPageSafeOffset, List1& previouslyMeasuredOffsets, Nullable1& lastPagePixelSize, Boolean remeasure) at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint) 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.InvokeOnRenderCallback.DoWork() 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 System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj) 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 MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext 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 System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, 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.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at System.Windows.Application.RunDispatcher(Object ignore) at System.Windows.Application.RunInternal(Window window) at System.Windows.Application.Run(Window window) at System.Windows.Application.Run() at StatScreen.App.Main()

This only happens when selecting an already placed control, not when drawing or editing it initially. Must click out then back in.

jogibear9988 commented 5 years ago

Can you show your XAML? And wich DLL I need to include?

JoshWobbles commented 5 years ago

If by dll to include you mean my user control, it is just a slight modification to the generic MediaElement to allow looping;

    public class LoopableMediaElement : MediaElement
    {
        public bool Loop
        {
            get { return (bool)GetValue(LoopProperty); }
            set { SetValue(LoopProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LoopProperty =
            DependencyProperty.Register("Loop", typeof(bool), typeof(LoopableMediaElement), new PropertyMetadata(true));

        public LoopableMediaElement()
        {
            this.MediaEnded += LoopableMediaElement_MediaEnded;
        }

        private void LoopableMediaElement_MediaEnded(object sender, RoutedEventArgs e)
        {
            if (Loop)
            {
                this.Position = TimeSpan.FromMilliseconds(1);
            }
        }
    }

Beyond that everything is plain Jane and my IDE XAML is pretty much identical to the sample code provided here.

jogibear9988 commented 5 years ago

Could not reproduce... Could you not debug it? Or use PDB's so we have a Line Number?

JoshWobbles commented 5 years ago

Line 61, TimeSpanEditor.xaml.cs;

var value = (TimeSpan) PropertyNode.DesignerValue;

but during the debug even though it throws a NullRef, I can see that it does in fact have a value when i mouse over during the break. Race condition possibly?

JoshWobbles commented 5 years ago

For reference I have a .mov video in the MediaElement that is auto playing if that makes any difference when you tested.

JoshWobbles commented 5 years ago

System.NullReferenceException HResult=0x80004003 Message=Object reference not set to an instance of an object. Source=ICSharpCode.WpfDesign.Designer StackTrace: at ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.TimeSpanEditor.NumberEditor_DataContextChanged(Object sender, DependencyPropertyChangedEventArgs e) in C:\projects\wpfdesigner\WpfDesign.Designer\Project\PropertyGrid\Editors\TimeSpanEditor.xaml.cs:line 61

Console outputs:

ICSharpCode.WpfDesign.PropertyGrid.PropertyNode.DesignerValue.**get** returned null.

But DesignerValue is definitely not null when I mouse over it during the debug break

JoshWobbles commented 5 years ago

Ok, some more troubleshooting, this doesn't seem to throw an error until I save and reload the xaml. Despite the XAML being identical from the first save to consecutive saves, It only throws the error after the document has been loaded using designSurface.LoadDesigner(xmlReader, loadSettings);

JoshWobbles commented 5 years ago

Figured id bring the discussion back to this thread.

I tried a new project using the demo code and still same error. The XAML below will alwayse throw an exception when trying to edit a property in the property control.

        private static string xaml = @"<Grid 
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
xmlns:d=""http://schemas.microsoft.com/expression/blend/2008""
xmlns:mc=""http://schemas.openxmlformats.org/markup-compatibility/2006""
mc:Ignorable=""d""
x:Name=""rootElement"" Background=""White"">
<MediaElement Source=""C:\Users\jhebb\Videos\2019-03-15 10-25-29.mp4""/>
</Grid>";

Make sure to change the Source path to a valid local video.

JoshWobbles commented 5 years ago

my source: https://dsdcomputers.visualstudio.com/_git/WpfDesigner-MediaElement

jogibear9988 commented 5 years ago

your source does not contain any code...

JoshWobbles commented 5 years ago

@jogibear9988 that was weird, I just pushed again, looks like its up now, not much to it though like I said, the difference is just loading xaml that has a mediaelement with a video source

JoshWobbles commented 5 years ago

In this example I am actually able to see the DesignerValue property is infarct null, a ?? at line 61 in TimeSpanEditor.xaml.cs may be a workaround for the issue, but the actual fix may be seeing why the property does not properly populate after parsing from XAML using your LoadDesigner.

jogibear9988 commented 5 years ago

Problem is the IsAmbiguous check in PropertyNode. It return true, cause the Video is Playing and the time is read 2 times and is then different!

So the TimeSpan Editor should also work when the value is null, I'll fix it

JoshWobbles commented 5 years ago

AWSOME! I was just digging into the TypeEditor seeing if it was possible to override the TimeSpanEditor for my use case, but if the problem was in fact reproducible then this is even better!

Looking forward to the NuGet push to test it out in my production project but at first glance looks like that should catch the issue just fine!

Just out of curiosity though now that I see that this editor does implement some sort of TypeEditor attributes, how would I go about implementing my own, does the property grid automatically recognize that attribute? is there a way to override an existing TypeEditor like for example in this case if I needed to do so?

jogibear9988 commented 5 years ago

I think the last one should be used.

You need to register your assembly via EditorManger.RegisterAssembly

jogibear9988 commented 5 years ago

In my WPF Application I added complete PropertyPages depending on the Type, and use the WpfDesigner Propertygrid as a fallback for unpopular Properties. I'll look to extend one of the samples to show how easy this is, especially when you use the DesignItemBinding