When interacting with custom controls on your pages from C/AL, you must be absolutely sure that the control has been instantiated. If it is not, you’ll get an error such as this:
The reason why this happens is that C/AL code gets to execute before the page has been rendered, and thus also before the custom controls have been instantiated.
Your first idea might be to use the ISNULL system function and check if control is instantiated, for example, like this:
This will compile, but it will fail because the controls will never be NULL. In my opinion it is a flaw in the .NET Interoperability implementation, but it could be argued the other way around (like, for example, that the CurrPage.Name is just a placeholder for a control, but that explanation would not hold up against the whole concept of how you are accessing and interacting with the controls). Whatever it is, a bug or a feature, it does not work and you need to do something else.
That something else is creating an event, which I like to call ControlAddInReady (it may have any name you like). This is how the control add-in code could look with this event added:
This will expose a new event trigger in your C/AL code, which you can use to change the code like this:
This makes sure that you only access the control add-in if it has been instantiated.
Now, the only thing that remains is to raise this ControlAddInReady event from your C# control code. And here comes a tricky part, because if you think the following piece of code solves the problem, you are wrong:
This is a standard event-rising pattern in C#, and it compiles, and executes nicely, however, when this code is hit, the ControlAddInReady is indeed null, and no event handlers are attached to it, therefore, the event never fires.
Let me first explain why it never fires. When the extensibility framework calls the CreateControl method, it may not yet have completed the rendering of the page, and therefore the C/AL event triggers for the control events (such as this ControlAddInReady event trigger) on the page have not yet been bound as event handlers for events. This binding may happen at a later stage, after the CreateControl has already completed its work. Now, I said “may” two times, because depending on how exactly you implement your control (which class you inherit from or which interfaces you implement), it may or may not be true. Again – this could just be another bug in the extensibility framework, or another feature which you have to cope with. In any case, just checking if ControlAddInReady is assigned will not do the trick, as in most situations the event handlers are just never assigned when this block of code is hit.
And now let me explain how to implement it properly.
When the extensibility framework calls the CreateControl method, it has not yet completed the rendering of the page and it has not yet placed the control onto the page. If you want, the control exists only in memory. When the rendering of the page completes, the control you created in the CreateControl method is placed onto the page, and in terms of Windows Forms terminology, it’s parent has changed. At this time, all the event triggers have been properly bound as event handlers in your control, so the only thing you need to do is to respond to the ParentChanged event of the control you instantiated. In effect, this is what your code should look like:
Here, I’ve used a lambda syntax, but if you are not yet on friendly terms with lambdas in C#, this is what it effectively translates to:
And when you do it like this, you fire the ControlAddInReady trigger when the parent of the _textBox control (or whichever other control you instantiate) changes, which is at the time the control is actually placed on the page.