We think, EnabledIf attribute have UI refresh issue

Hi Team,

We think EnabledIf attribute have an UI refresh issue, if the value is set also , it is not reflected in the UI in some cases.

Let me explain,

I have a combo box, which is of KindOfLimits (ENUM) type

 public KindOfLimits Kinds
        {
            get { return this.kinds; }
            set
            {
                this.kinds = value;
                this.OnPropertyChanged(nameof(this.Kinds));             
               
            }
        }

I have an custom control (IControlProvider) which will be enabled only if KindOfLimits== NominalTolerance and AssignVaribaleFrom==UserInput.

[ConvertToArrayViewIfCanAttribute(nameof(Tolerance), nameof(DataTypeSelected))]
[EnabledIf(nameof(AssignVaribaleFrom), AssignmentType.UserInput, HideIfDisabled = true)]
[EnabledIf(nameof(Kinds), KindOfLimits.NominalTolerance, HideIfDisabled = true)]
[Display("Check", Order: 0.1)]
public string Tolerance
{
    get;set;
}

About our custom control(ConvertToArrayViewIfCanAttribute):
Depending on the datatype selected custom control will display a textbox or a combobox.

Problem we face :
For the first time when we assign value to Kinds and AssignVaribaleFrom . UI is not updated.
When we click on another test step and come back then UI will be okay.

Work Around we do:
if we do the following way then it is okay.

Task.Run(() =>
{
Thread.Sleep(200);
this.OnPropertyChanged(nameof(this.Tolerance));
});

eg:

    public KindOfLimits Kinds
    {
        get
        {
            return this.kinds;
        }
        set
        {
            this.kinds = value;
            this.OnPropertyChanged(nameof(this.Kinds));

            Task.Run(() =>
            {
                Thread.Sleep(200);
                this.OnPropertyChanged(nameof(this.Tolerance));
            });
        }
    }
2 Likes

Thanks @justin_c_i . Is this something you saw where the behavior changes with a specific version of OpenTAP?

If you click out of the entry field does the UI update or does it have to be opening a different Test Step and returning?

1 Like

Is this something you saw where the behavior changes with a specific version of OpenTAP? - We tested only in 9.12.

If you click out of the entry field does the UI update or does it have to be opening a different Test Step and returning?- If we click on the entry field then also field will get updated. we don’t need to click on another test step.

2 Likes

I think this is somewhat intentional to prevent multiple updates as the input changes. It only updates when the context changes, but I can submit something to see if we can improve this behavior.

2 Likes

Okay, Thanks for the support. :slight_smile:
We use our work around for time being .

2 Likes

Hi Justin,

Do you see this issue when used with your IControlProvider or does it also occur for eg. a text box control?

1 Like

@rolf_madsen we don’t see this issue when we use without IControlProvider.
Becasue there is no UI change if we use without IControlProvider.

2 Likes

I don’t understand, but if you can describe how to reproduce the issue in a simple way, we can probably fix it in 9.13.

2 Likes

I will try to create a simple custom control, and try to simulate this issue. Thanks.

2 Likes

@justin_c_i Not sure if this will help, but it has helped me with similar issues of updating the UI from a custom IControlProvider. Try calling OnPropertyChanged from the IControlProvider (or its view model), instead of relying on the OnPropertyChanged call at the test step property level. Here’s a snippet:

IMemberAnnotation memAnn = annotations.Get<IMemberAnnotation>();
(annotations.Source as ValidatingObject).OnPropertyChanged(memAnn.Member.Name);
2 Likes

Hi @david-wsd ,
I m already using something like this.

        public void RefreshProperty(CustomAnnotaionCollection customAnnotationMain)
        {
            try
            {
                var stringValueProvider = customAnnotationMain.baseAnnotationCollection.Get<IStringValueAnnotation>();
                (customAnnotationMain.baseAnnotationCollection.Source as TestStep).OnPropertyChanged(nameof(stringValueProvider));
            }
            catch
            {
                // Hanldes Exception
            }
        }

Problem I feel is like EnabledIF have high UI priority than the ICustomProvider.

Like, EnabledIF Property will be hidden in the UI,
Depending on another properties only it will be visible in the UI,

When EnabledIF is displayed in the UI for the first time, it takes basic control .(Even if EnabledIF property need to display a combobx depending on customProvider, it still displays a Textbox).

When I refresh the EnabledIF property in another thread then CustomProvider control is displayed.

I feels UI rendering for hidden properties is occurred in the following way .
ICustomProvider -> EnabledIF(Which displays a Textbox always).

I feels UI rendering for Visible properties is occurred in the following way .
EnabledIF-> ICustomProvider -> (Which displays a custom control).

And Also if EnabledIF is rendered in the GUI once then it works normal.(then we enable or disable the EnabledIF consitions also still it works as expected,).

Only for the first time this issue have.

Thank you very much @david-wsd for the support.

Regards
Jestin CI

Hi @justin_c_i, cool, that looks about like what I typically do.

You said the IControlProvider is conditionally returning a combobox. Does that mean that the control provider’s CreateControl() function is checking the value of DataTypeSelected, and based on that it will either return a combobox, or null? (thereby defaulting to OpenTAP’s default textbox control provider)

Hi @david-wsd
Does that mean that the control provider’s CreateControl() function is checking the value of DataTypeSelected, and based on that it will either return a combobox, or null?-- Based on Datatype selected CreateControl() will return a combobox or a button.

unfortunately for the first time a Textbox is displayed in the GUI.

@justin_c_i Interesting. So the very first time, it’s ignoring the control you’ve created in CreateControl(), and is instead using opentap’s default textbox control.

What happens if you set EnabledIf’s HideIfDisabled to false?
Or, what happens if you remove the EnabledIf attribute entirely?

Do either of the above modifications result in the correct control being displayed at all times?

What happens if you set EnabledIf’s HideIfDisabled to false?- ICutomProvider works correctly.
Or, what happens if you remove the EnabledIf attribute entirely?- ICutomProvider works correctly.

Do either of the above modifications result in the correct control being displayed at all times? - Yes, Then ICustomProvider works normally. Becasue we are using this custom control in 70+ Test steps and we never encountered any error like this…Only for EnabledIf we saw this first time issue

1 Like

Thanks for confirming, @justin_c_i. I agree with you, it sounds like an issue specific to the EnabledIf attribute, as your post title states.

I’m curious if CreateControl is even being called the first time.

I’m curious if CreateControl is even being called the first time.-- Yes, I tried putting a break point in Create control… it got hit.

Hi @brennen_direnzo was there ever a resolution to this in the OpenTAP code? I’m having the same problem, where EnabledIf is applied (with HideIfDisabled is set to true) to a method in a custom Dialog, not a TestStep, but this is not updating, even when implementing INotifyPropertyChanged and using OnPropertyChanged.

@john.berlien I don’t think anything was specifically done in OpenTAP to address this. Can you create a new issue?

1 Like

Work Around We Do is

Task.Run(() =>
{
Thread.Sleep(200);
this.OnPropertyChanged(nameof(this.Tolerance));
});

Example:

public KindOfLimits Kinds
    {
        get
        {
            return this.kinds;
        }
        set
        {
            this.kinds = value;
            this.OnPropertyChanged(nameof(this.Kinds));

            Task.Run(() =>
            {
                Thread.Sleep(200);
                this.OnPropertyChanged(nameof(this.Tolerance));
            });
        }
    }
[EnabledIf(nameof(Kinds), KindOfLimits.NominalTolerance, HideIfDisabled = true)]
[Display("Check", Order: 0.1)]
public string Tolerance
{
    get;set;
}