15

I am having a problem with a setting the enabled state of a button on a Dialog. The button in question is defined as:

<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Condition Action="disable">Validated = 0</Condition>
<Condition Action="enable"><![CDATA[Validated <> 0]]></Condition>
<Publish Event="EndDialog" Value="Return">1</Publish>
</Control>

The property Validated starts out at an initial value of 0, and as expected the next button starts out disabled.

<Property Id="Validated" Value="0"/>

The property itself is modified through a Custom Action on another button.

<Control Id="PerformValidation" Type="PushButton" X="225" Y="75" Width="50" Height="20" Text="Validate">
<Publish Event="DoAction" Value="ValidateDB">1</Publish>
</Control>

With a stripped down version of the Custom Action like:

[CustomAction]
public static ActionResult ValidateDatabase(Session session)
{
session.Log("Begin ValidateDatabase");
session["Validated"] = "1";
return ActionResult.Success;
}

The problem I face is that the Next button does not re-enable itself after the Custom Action has run. I can confirm that the CA does run, and the property is successfully set. The UI will update if I do some other action that causes it to refresh, e.g. go back a page then forward to this page again and the Next button will be enabled.

Any ideas on how to refresh a buttons state after a Custom Action?

BBoy
  • 1,063
  • 1
  • 10
  • 21

2 Answers2

18

http://www.mail-archive.com/wix-users@lists.sourceforge.net/msg05097.html gives an solution to republish the properties that were changed in the custom action immediately after it.

Here is an example of how I have gotten it to work in my code:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <Binary Id="ConnectionStringExtension.dll" SourceFile="$(var.ConnectionStringExtension.TargetDir)$(var.ConnectionStringExtension.TargetName).CA.dll" />
        <CustomAction Id="MyCustomAction" BinaryKey="ConnectionStringExtension.dll" DllEntry="VerifyConnectionString" Execute="immediate"  />

        <UI>
            <Dialog Id="ConnectionStringDlg" Width="370" Height="270" Title="Database Settings - [ProductName]" NoMinimize="yes">
                <Control Id="ConnectionStringLabel" Type="Text" X="45" Y="73" Width="100" Height="15" TabSkip="no" Text="&amp;Connection String:" />
                <Control Id="ConnectionStringEdit" Type="Edit" X="45" Y="95" Width="220" Height="15" Property="CONNECTION_STRING" Text="{200}" />
                <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="&amp;Back">
                </Control>
                <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="&amp;Next">
                    <Condition Action="enable"><![CDATA[CONNECTION_STRING <> "" AND CONNECTION_STRING_VALID = "1"]]></Condition>
                    <Condition Action="disable"><![CDATA[CONNECTION_STRING = "" OR CONNECTION_STRING_VALID = "0"]]></Condition>
                </Control>
                <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="Cancel">
                    <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
                </Control>
                <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="WixUI_Bmp_Banner" />
                <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
                    <Text>Please enter database configuration</Text>
                </Control>
                <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
                <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
                    <Text>{\WixUI_Font_Title}Database Settings</Text>
                </Control>
                <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
              <Control Id="VerifyButton" Type="PushButton"  Width="56" Height="16" X="45" Y="118" Text="Verify">
                <Publish Event="DoAction" Value="MyCustomAction">1</Publish>
                <Publish Property="TEMP_VERIFIED" Value="[CONNECTION_STRING_VALID]">1</Publish>
                <Publish Property="CONNECTION_STRING_VALID" Value="[TEMP_VERIFIED]" />
              </Control>
            </Dialog>
        </UI>
    </Fragment>
</Wix>

The CustomAction sets the value of CONNECTION_STRING_VALID to either 1 or 0 depending if it is valid or not and I have defined elsewhere that by default its value is 0

<Property Id="CONNECTION_STRING_VALID" Value="0" />

Now when I click my verify button if the string is valid the next button is enabled

Daniel Powell
  • 8,143
  • 11
  • 61
  • 108
  • That worked beautifully. In my opinion a much better solution than the twin dialog approach. I do, however, experience a few seconds delay between when the action is complete, and the button is activated. Definitely not a problem, just a curiosity. – bigfoot Nov 02 '11 at 11:14
  • Been a while since I used it but from memory it was pretty instantaneous for me, maybe something to do with your action? – Daniel Powell Nov 02 '11 at 22:17
  • Publishing was the key for me ( – Owen Ivory Jan 10 '19 at 23:43
6

This is a well-known limitation of Windows Installer. The state of the dialog doesn't change until you refresh it in any other way, for instance, moving back and forward, as you correctly mentioned.

The workaround here is to have two identical dialogs, DialogA and DialogB. The PerformValidation button on DialogA will perform validation as it does right now and call DialogB (as NewDialog). The same way, the PerformValidation button on DialogB will also perform validation and call DialogA. Thus, you'll have the dialogs to be loaded each time you run validation and button state will be correctly displayed. The user won't suspect anything, because he/she will only see the same dialog. :-)

The idea is described better in detail here. It is called "twin dialogs".

Hope this helps.

Yan Sklyarenko
  • 31,557
  • 24
  • 104
  • 139
  • 1
    Thanks Yan, I will employ this technique. Its a pity that the Windows installer is so limited. :) – BBoy Nov 22 '10 at 23:21
  • It is possible without a twin dialog, I just don't quite understand how it works am trying to figure it out know, see http://msiext.codeplex.com and check out their CommonUiMsi.msi installer, it has a DB creation screen with a verify button that enables after success, the source is there and they do not appear to be using a secondary dialog, I have a feeling it has something to do with how they publish their properties but still trying to figure it out. – Daniel Powell Jun 21 '11 at 06:10