The phenomenon that other UI components are not visible when using Revit API.

The phenomenon that other UI components are not visible when using Revit API.

Anonymous
Not applicable
2,826 Views
22 Replies
Message 1 of 23

The phenomenon that other UI components are not visible when using Revit API.

Anonymous
Not applicable

Hello.

 

When developing Revit, I am an Addin that I control in a new window when I click a button.

 

This window is using an external UI component. (hereinafter referred to as Telerik)
Telerik assemblies are loaded in OnStartup() .

 

The A button in the A project is telerik version 1.0.0. (A.addin)
The B button in the B project is telerik version 1.3.3. (B.Addin)
(Think of it as creating different project addins.)

 

In this case, A button and B button exist as different add-ins in Revit.

 

Clicking the A button opens a new window, but the Telerik UI is not shown. Example) Window combobox is visible, telerik.combobox is not.
Clicking the B button opens a new window and displays all UI.

 

That is, if A and B are loaded, window B is shown and window A is not shown. -> In this case, only the last telerik loaded version will show the UI.
And if you delete B.Addin and run it when only A is left, you can see A window well.

 

I have previously contacted telerik's support center and inquired with revit running.
The telerik developer's answer speculates that there is a conflict between the revit api mechanism and the telerik mechanism.
This is very specific and I've never seen it before.
Also, even if the telerik version is different, the ui should be displayed normally.

 

I can't find a solution to this, please help.
I posted on this forum, but I also want to ask if there is a separate support center for the revit api.
Thanks.

0 Likes
Accepted solutions (2)
2,827 Views
22 Replies
Replies (22)
Message 2 of 23

jeremy_tammik
Alumni
Alumni

Ensure that you are setting the Window parent properly:

 

https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.parent

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 23

Anonymous
Not applicable

hello.

 

I don't know the meaning of your words.

'Ensure the parent of the created window?'

 

I think it has nothing to do with it, but why?

The only difference is that the UI is visible and invisible when used in different versions of different projects. Does this have anything to do with it?

0 Likes
Message 4 of 23

ricaun
Advisor
Advisor

I don't know how this Telerik works and could be interesting to check these two projects if possible, I suppose is basically the same project with a different Telerik version.

 

And I know Revit and Windows application does not work very well with two different versions of the same AssemblyName loaded at the same time, usually, the application sees only one version of the Assembly... You could try to show what version of the Telerik the addin is using when is loaded on Revit.

 

With something like this:

typeof(TelerikClass).Assembly.GetName().Version

 

Put on the description of the button, or something. =D

 

I supposed if the two versions were the same the two plugins works like intended.

 

I hope this helps, see yaa!

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 5 of 23

Anonymous
Not applicable

Hello.

 

First of all, you can think of telerik as a UI library such as devexpress.

What you mean is that even for non-revit windows applications, if the assembled version is different, the ui is not displayed.
Is my understanding correct?

 

If this is correct I asked the telerik support developer: "Does telerik show the same UI even if the assembly is loaded with a different version? (when using a program other than Revit)"
His answer is "regardless where the Telerik assembly is loaded (in one or more projects), you should see the same UI."
That is, it doesn't matter.

 

Doing the same version you suggested can cause problems later.

For example, A is version 1 and B is number 2.

There were no errors in version A, but there may be cases where certain properties are changed while updating in version B and an error may occur.

 

Because of this case, I want to display the UI while maintaining the version for each project.

 

If there is any other way, please let me know more. 🙂

0 Likes
Message 6 of 23

ricaun
Advisor
Advisor

I don't know why is not showing the other UI, each library works differently than others, and I supposed Revit Application only sees one Assembly...

 

Does not matter the version are you using, the Application search for the AssemblyName and try to use it, does not matter if is version 1.0.0 or 1.3.3, gonna use the first and ignore the rest. If the library is not prepared for this kind of scenario, gonna have some random behavior.

 

If you are not able to use the same version of the Telerik library on the addin A and B, defiantly some are wrong with the library or with your addin implementation.

 

Definitely gonna be a pain to maintain these addins...

 

Third-party library always is a pain to work with.

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 7 of 23

Anonymous
Not applicable

Ummm... I think you misunderstood because I didn't explain enough.

 

I have several versions in use, so I think the version is important.(UI library version)

 

When add-ins A and B use the same version of telerik library, the UI is displayed normally.

However, if the versions are different, 1.0.0 and 1.3.3 will recognize that the last assembly is loaded and only one will be displayed.

 

This means that if you use the two assemblies in different window applications, the UI will look the same for both. But in Revit, I say, not so.

 

About this, I contacted the telerik development support team and the answer was that it is speculation that there is a conflict between Revit and the mechanism, and that this is the first case.

0 Likes
Message 8 of 23

ricaun
Advisor
Advisor

I understand the situation! The problem is you are trying to load two different versions of the same library in a Windows application, you are not supposed to do that.


Revit probably only loads one of them, the windows application does not need to load the other Assembly if already is load. If the AssemblyName is the same the version does not matter.


You could try to look on the AppDomain.GetAssemblies and check if is loaded the version 1.0.0 and 1.3.3.


You said "Telerik assemblies are loaded in OnStartup()" I really don't know how are you doing this load, something sneak!


Without a source code is really hard to discover how to fix the issue.

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 9 of 23

Anonymous
Not applicable

I made a sample file.

Can you confirm if it's ok?

 

As of 2021 Revit, I have Project.sln and Bproject.sln.
Just set the addin path and move the folder.

 

This is like the video I attached.

The source code is very simple, so even if you do not run it directly, you can check the assembly loaded part.

(Sample files will be deleted after about a week.)

 

ps. I have confirmed that the AssemblyName is the same. When debugging only one project, what version is loaded with GetAssemblies is checked.

0 Likes
Message 10 of 23

ricaun
Advisor
Advisor
Accepted solution

Thanks for sharing the project,

I try a lot of things and didn't have any success, I supposed is something related to the library, how the library loads the UI elements.

 

I remove the Assembly.Load and use some Class in the library and get the assembly:

 

 

_ = typeof(Telerik.Windows.Controls.RadButton).Assembly;
_ = typeof(Telerik.Windows.Controls.Input.ParseMode).Assembly;
_ = typeof(Telerik.Windows.Data.Data.Hierarchy.IHierarchyDescriptor).Assembly;

 

 

This does not work, unfortunately, the Application loads two versions of the same Telerik library, and by the looks UI breaks if has more the one library load on the main Application (Revit).

 

Check the video I force to load another Telerik and the UI breaks..

 

 

I guess the best thing to do is not use this UI libray, definitely gonna break if some other addin uses a different version...

 

See yaa

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 11 of 23

Anonymous
Not applicable

Thank you very much for giving us another test and letting us know the results.

 

I would like to avoid this too, but it can happen in unavoidable circumstances. (For example, when using an add-in with another company, the teleric version is different)

We wanted to eliminate the root cause... but we can't.

 

Thanks again!

0 Likes
Message 12 of 23

ricaun
Advisor
Advisor

One solution could be to change the AssemblyName of your Telerik, I don't know if gonna work but your Telerik library gonna be unique from the others.

 

I was looking for the ILRepack.Lib.MSBuild.Task another time to embed the library inside the main dll.

 

Theoretically is possible to send all the data of the 3 Telerik libraries to one dll with your own AssemblyName.

 

This could work but need to test.

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 13 of 23

ricaun
Advisor
Advisor
Accepted solution

The ILRepack.Lib.MSBuild.Task works...

 

I create a new Telerik.Windows.dll with all three DLLs.

 

 

The C project works fine, I could send you the assembly so you could test on some complex project.

 

But I'm supposed gonna work like intended and some other Telerik library not gonna interfere with your application.

 

This could be useful to create your own custom package.

 

See yaa!

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 14 of 23

Anonymous
Not applicable

Thank you so much!

 

I understood that Libs are bundled into one DLL and used.

 

Can I use this just by looking at the documentation? Or do you have any additional settings?

 

Because my xaml design uses a lot of telerik dll, but it is unified with schema presentation, so I need to test it. (8 dlls)

 

Thanks again! There seems to be a solution. 🙂

0 Likes
Message 15 of 23

ricaun
Advisor
Advisor

I really don't how schema presentation works and makes it harder to discover how to make works.

The presentation works with the attribute XmlnsPrefix and XmlnsDefinition on each assembly.

 

Here is my project configuration.

 

<ItemGroup>
  <PackageReference Include="ILRepack.MSBuild.Task" Version="*" IncludeAssets="build; compile" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
  <Reference Include="Telerik.Windows.Controls">
    <HintPath>.\ref\Telerik.Windows.Controls.dll</HintPath>
  </Reference>
  <Reference Include="Telerik.Windows.Controls.Input">
    <HintPath>.\ref\Telerik.Windows.Controls.Input.dll</HintPath>
  </Reference>
  <Reference Include="Telerik.Windows.Data">
    <HintPath>.\ref\Telerik.Windows.Data.dll</HintPath>
  </Reference>
</ItemGroup>

<Target Name="ILRepacker" AfterTargets="Build">
  <PropertyGroup>
    <WorkingDirectory>$(MSBuildThisFileDirectory)$(OutDir)</WorkingDirectory>
  </PropertyGroup>
  <ItemGroup>
    <InputAssemblies Include="$(TargetPath)" />
    <InputAssemblies Include="@(ReferencePathWithRefAssemblies)" Condition="'%(filename)' == 'Telerik.Windows.Controls'" />
    <InputAssemblies Include="@(ReferencePathWithRefAssemblies)" Condition="'%(filename)' == 'Telerik.Windows.Controls.Input'" />
    <InputAssemblies Include="@(ReferencePathWithRefAssemblies)" Condition="'%(filename)' == 'Telerik.Windows.Data'" />
  </ItemGroup>

  <!-- https://github.com/peters/ILRepack.MSBuild.Task/blob/master/src/ILRepack.MSBuild.Task/ILRepack.cs -->
  <ILRepack AllowDuplicateResources="true"
            Union ="false" DebugInfo="true" 
            CopyAttributes="true" AllowMultiple="true" Parallel="true" Internalize="false"
            OutputType="$(OutputType)" MainAssembly="$(AssemblyName).dll"
            OutputAssembly="$(AssemblyName).dll" InputAssemblies="@(InputAssemblies)"
            WilcardInputAssemblies="true" InternalizeExcludeAssemblies="@(InternalizeExcludeAssemblies)"
            WorkingDirectory="$(WorkingDirectory)" />
</Target>

 

 

The documentation is not so clear but the thing you definitely need to set is the Internalize="false", this makes the embedded class public indeed of internal.

 

If you find a way to make the schema presentation works please let me know.

By enabling the CopyAttributes="true" and AllowMultiple ="true" forces to copy all the attributes including the XmlnsDefinition and XmlnsPrefix to enable the presentation schema.

 

See yaa!

 

Edit: Add CopyAttributes="true" AllowMultiple ="true" to copy the XmlnsDefinition and XmlnsPrefix

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 16 of 23

ricaun
Advisor
Advisor

Hello @Anonymous 

 

I was messing around and found a way to add the presentation on the bundle dll.

 

You could add on the AssemblyInfo.cs the following codes to enable the presentation.

using System.Windows.Markup;
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Shapes")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Controls")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Controls.TransitionEffects")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Controls.Animation")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Controls.DragDrop")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Controls.Behaviors")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Controls.Primitives")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Controls.Legend")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.DragDrop")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.DragDrop.Behaviors")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Input.Touch")]
[assembly: XmlnsDefinition("http://schemas.telerik.com/2008/xaml/presentation", "Telerik.Windows.Data")]
[assembly: XmlnsPrefix("http://schemas.telerik.com/2008/xaml/presentation", "telerik")]

 

You can find the Attributes using this code on the Assembly.

 

/// <summary>
/// Get <see cref="XmlnsPrefixAttribute"/> and <see cref="XmlnsDefinitionAttribute"/> as assembly format.
/// </summary>
/// <param name="assembly"></param>
/// <returns></returns>
private IList<string> GetXmlnsCustomAttributes(Assembly assembly)
{
    var attributes = new List<string>();
    foreach (var attr in assembly.GetCustomAttributes<XmlnsPrefixAttribute>())
    {
        string prefix = $"[assembly: XmlnsPrefix(\"{attr.XmlNamespace}\", \"{attr.Prefix}\")]";
        attributes.Add(prefix);
    }
    foreach (var attr in assembly.GetCustomAttributes<XmlnsDefinitionAttribute>())
    {
        string definition = $"[assembly: XmlnsDefinition(\"{attr.XmlNamespace}\", \"{attr.ClrNamespace}\")]";
        attributes.Add(definition);
    }
    return attributes;
}

 

See yaa!

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 17 of 23

Anonymous
Not applicable

Hello.

 

I've been busy and haven't been able to properly verify it's working yet. sorry.

 

And I'm trying to use ILMerge rather than ILRepack.MSBuild.Task with your inspiration.

 

I understand how to add AssemblyInfo. But how can I load it into xaml?

<Window x:Class:~~~~~
      xmlns="~~~~" 
      ...
      xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation">
<telerik:RadGridview ... />
<telerik:RadComboBox ... />


If I simply define it in asseblyinfo, is there any problem if I use it as above? Can't test because the merged dll file doesn't exist yet.

 

Thanks for replying even after a while 🙂

 

0 Likes
Message 18 of 23

ricaun
Advisor
Advisor

Should work fine.

 

I changed the reference on the AProject and works like a champion, didn't need to change any xaml file.

 

Gonna send my compiled version in private.

 

See yaa

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 19 of 23

ricaun
Advisor
Advisor

Found a better way without copying any of the Xmlns Attributes.

 

On the ILRepack I kinda miss the AllowMultiple option with the CopyAttributes that forces copy the attributes of the InputAssemblies to the OutputAssembly.

 

Gonna edit the post and add missing options.

 

Nice.

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 20 of 23

Anonymous
Not applicable

Thanks to the test file, it was easier to check.

As a result, it works exactly.

 

When I have enough time, I will use ILRepack first and then apply it.

 

Could you tell me how you did the assembly loading via static method?

 

Thank you for your interest in my post despite the passage of time. ^^b

0 Likes