helix-toolkit / helix-toolkit

Helix Toolkit is a collection of 3D components for .NET.
http://helix-toolkit.org/
MIT License
1.84k stars 661 forks source link

Binding changing text to Button2D #1385

Open amescodes opened 4 years ago

amescodes commented 4 years ago

we're building a plugin for Autodesk Revit that utilizes Helix Toolkit for its viewer. we're trying to add a Button2D to a viewport that will change text when clicked on, flipping between two different strings. here's what we have so far:

in xaml:

<hx:Viewport3DX.Content2D>
    <hx2D:StackPanel2D Orientation="Vertical" 
        HorizontalAlignment="Right" 
        VerticalAlignment="Bottom"
        Width="75">
        <hx2D:Button2D 
            HorizontalContentAlignment="Center" 
            VerticalContentAlignment="Center" 
            Content2D="{Binding foldUnfoldButtonText}" 
            Command="{Binding changeUnfoldDisplay}" 
            Margin="5" 
            Padding="3" />
    </hx2D:StackPanel2D>
</hx:Viewport3DX.Content2D>

in mainviewmodel:

    showUnfoldedPanel = false;
    foldUnfoldButtonText = "Fold";
    //SceneNode2D foldUnfoldSceneNode = new TextNode2D()
    //{
    //    Text = foldUnfoldButtonText
    //};
    //foldUnfoldTextNode2D = new ClickableNode2D()
    //{
    //    Content = foldUnfoldSceneNode
    //};

    changeUnfoldDisplay = new relayCommand(x => updatedUnfoldedGeometryPreview());
//show unfolded geometry logic
private void updatedUnfoldedGeometryPreview()
{
    showUnfolded = !showUnfolded;
    foldUnfoldButtonText = (showUnfolded) ? "Unfold" : "Fold";
}

whenever the window is opened, it throws a null reference exception (below) at InitializeComponent(), and the app and Revit crash. we've checked the DataContext when it throws the exception and none of the variables are null by the time InitializeComponent() is hit. is there a different way we should be binding to this? you can see we've tried using Node2D which also failed, and also tried this with a value converter that didn't work either.

at HelixToolkit.Wpf.SharpDX.Elements2D.ContentElement2D.<>c.<.cctor>b__25_1(DependencyObject d, Object e)
at System.Windows.DependencyObject.ProcessCoerceValue(DependencyProperty dp, PropertyMetadata metadata, EntryIndex& entryIndex, Int32& targetIndex, EffectiveValueEntry& newEntry, EffectiveValueEntry& oldEntry, Object& oldValue, Object baseValue, Object controlValue, CoerceValueCallback coerceValueCallback, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, Boolean skipBaseValueChecks)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.Baml2006.WpfMemberInvoker.SetValue(Object instance, Object value)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value)
at System.Xaml.XamlObjectWriter.Logic_ApplyPropertyValue(ObjectWriterContext ctx, XamlMember prop, Object value, Boolean onParent)
at System.Xaml.XamlObjectWriter.Logic_DoAssignmentToParentProperty(ObjectWriterContext ctx)
at System.Xaml.XamlObjectWriter.Logic_AssignProvidedValue(ObjectWriterContext ctx)
at System.Xaml.XamlObjectWriter.WriteEndObject()
at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
at unfoldApp.appUI.InitializeComponent() in ......
holance commented 4 years ago

2D controls in helixtoolkit have not been fully tested. Can you use wpf controls?

amescodes commented 4 years ago

got it. yes i can, i just saw the example with the 2d buttons within the viewport and thought i could implement similarly but with text binding. is it possible to get a similar effect with wpf controls?

chrkon commented 3 years ago

I have changed the D2DScreenMenuExample to reproduce this issue. I have just added this binding <hx2D:Button2D Content2D="{Binding VM2D.Text}" /> into the XAML code and immediately I got a NullReferenceException: Object reference not set to an instance of an object. message with this stack trace:

 at HelixToolkit.Wpf.SharpDX.Elements2D.ContentElement2D.<>c.<.cctor>b__25_1(DependencyObject d, Object e)
   at System.Windows.DependencyObject.ProcessCoerceValue(DependencyProperty dp, PropertyMetadata metadata, EntryIndex& entryIndex, Int32& targetIndex, EffectiveValueEntry& newEntry, EffectiveValueEntry& oldEntry, Object& oldValue, Object baseValue, Object controlValue, CoerceValueCallback coerceValueCallback, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, Boolean skipBaseValueChecks)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
   at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.Activate(Object item)
   at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
   at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)
   at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
   at MS.Internal.Data.DataBindEngine.Run(Object arg)
   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)

So I take a look on this!