SolidDNA get view of a drawing

Hi,
I’ve a question about SolidDNA, I don’t know it it is the right place to answer by since I see @PeterBrinkhuis hang around here I figure I should try.

I’m developing a SolidWorks add-in and I’m looking for a way to get the model referenced in a drawing.

With the native SolidWorks API, in C#, I can do something like this:

public static ModelDoc2 GetRootModel()
{
        DrawingDoc drwModel = (DrawingDoc)AddIn.swApp.ActiveDoc;

        View firstView = (View)drwModel.GetFirstView();

        while (firstView != null)
        {
            if (firstView.Type != (int)swDrawingViewTypes_e.swDrawingSheet)
            {
                goto exitLoop;
            }

            firstView = (View)firstView.GetNextView();
        }

        exitLoop:

        ModelDoc2 model = (ModelDoc2)firstView.ReferencedDocument;

        return model;
    }
}

It’s possible to have the seme results with SolidDNA? I saw it implements the method:

public void Views(Action<List<DrawingView>> viewsCallback)
        {
            // List of all views
            var views = new List<DrawingView>();

            // Get all views as an array of arrays
            var sheetArray = (object[])mBaseObject.GetViews();

            // Get all views
            foreach (object[] viewArray in sheetArray)
                foreach (View view in viewArray)
                    views.Add(new DrawingView((View)view));

            try
            {
                // Callback
                viewsCallback(views);
            }
            finally
            {
                // Dispose all views
                views.ForEach(view => view.Dispose());
            }
        }

but I’m inexperienced in C#, I don’t quite grasp the concept of delegates and lambda functions, and I can’t figure out how to use it.

Thanks in advance.

I just looked at the documentation and it doesn’t appear that this has been implemented yet in the SolidDNA framework the way you may be expecting.

To answer your question about the current documentation, you should be able to use this format to loop through the views and do essentially the same as the above.

Model refModel = default;
drwDocument.Views(views =>
{
    foreach (var view in views)
    {
        if ((view.UnsafeObject.Sheet?.CustomPropertyView == "Default") ||
            view.UnsafeObject.Sheet?.CustomPropertyView == view.Name)
        {
            refModel = new Model(view.UnsafeObject.ReferencedDocument);
            if (refModel != null)
            {
                break;
            }
        }
    }
});

If you want to consolidate it even more, you could do the same with:

Model refModel = default;
drwDocument.Views(views =>
{
    var view = views.FirstOrDefault(v => ((v.UnsafeObject.Sheet?.CustomPropertyView == "Default") ||
            v.UnsafeObject.Sheet?.CustomPropertyView == v.Name));
    refModel = new Model(view.UnsafeObject.ReferencedDocument);

});

Add additional error checking as necessary

Edit: For clarification on why I have the check for CustomPropertyView. This checks to see if the view matches the one in the sheet properties under the “Use custom property values from model shown in:”.

It supplies the first view if it’s “Default”, otherwise it iterates through until it finds the one specified explicitly. I suppose it’s not necessary for this example but I’ll leave it in with this explanation.

1 Like

Alex,
thanks for the detailed answer, I would never been able to get to it by myself.

Regarding the use of UnsafeObject: is that true that if I implement the code in your second sample, it will not require to dispose any object because the code doesn’t use any? I mean: the code uses methods related to unsafe objects, but because it doesn’t assign the objects there is no need to dispose?

I believe you’re correct that since we’re not creating an object referencing the UnsafeObject then we don’t need to worry about disposal.

1 Like

You called? :slight_smile:

The Views method is a bit strange and not user-friendly for beginners. I’m not really a fan of the methods that take an Action parameter, that’s all built by Luke before me.

To do something useful with the views, you can do something like this:

public static void Test()
{
    SolidWorksEnvironment.Application.ActiveModel.Drawing.Views(PerformActionOnViews);
}

private static void PerformActionOnViews(List<DrawingView> views)
{
    foreach (var drawingView in views)
    {
        var referenceModel = drawingView.UnsafeObject.ReferencedDocument;
    }
}

I don’t understand why @BigCrazyAl is using the CustomPropertyView, maybe he’s checking if the first is the sheet? If so, I’d use IView.GetType for that.

Be careful that the ReferencedDocument can be null if the underlying part or assembly is not loaded, so you may have to check that value before you create a Model from it.

In general, you don’t have to call Dispose on an UnsafeObject if you are not storing a reference to this object for a long time. Like storing the active model in a static variable that you keep in place for hours, even when the user changes the active model. Don’t do that if you don’t really need to.

I don’t think I use Dispose in any of my products. If you have a method where you get an UnsafeObject, use a property or call a method on it and don’t store the object for later use, you’ll be fine. As soon as the brackets of the method of if-statement close, the variable goes out of scope and the rest is taken care of by .NET.

2 Likes

@PeterBrinkhuis, I edited my post above but my goal was essentially to find the drawing view that the sheet references for its custom properties.

@PeterBrinkhuis : Shall I create a group called frameworks with SolidDNA as a subgroup. I will let you moderate it?

No thanks. Github works well for questions like these, but if people ask them here, I’ll answer anyway. We still get only a few questions per year.

1 Like