I would like to construct a Hierarchical TreeView in WPF from an available XML data.This Data could be Dynamic so Tree may end up having many levels of children. My sample XML looks like this:
<Groups>
<Group Name="Global" ID="1">
<Group Name="Demo - Marketing" ID="2" />
<Group Name="Demo - Finance" ID="3" />
<Group Name="Demo - Operations" ID="4" />
<Group Name="Demo - Sandpit" ID="5" />
<Group Name="Morson" ID="6">
<Group Name="Internal" ID="29">
<Group Name="Branch" ID="31">
<Group Name="Branch Components WIP" ID="50" />
<Group Name="MI32_IT Recruitment" ID="51" />
<Group Name="Branch Master" ID="52" />
<Group Name="Branch Master_Perm" ID="76" />
<Group Name="MI42_Manchester Rail Technical" ID="79" />
<Group Name="MI39_London Technical" ID="86" />
<Group Name="MI51_Oil & Gas London" ID="87" />
<Group Name="MI40_London Support Services" ID="88" />
<Group Name="MI28_Manchester Rail" ID="119" />
<Group Name="MI35_Heathrow" ID="125" />
<Group Name="MI73_London Telco" ID="150" />
<Group Name="MI04_EPB" ID="158" />
</Group>
<Group Name="Consultant" ID="32">
<Group Name="Consultant Master " ID="53" />
<Group Name="MI32_SBS_Steven Byrne" ID="57" />
<Group Name="MI32_RH_Robert Hoffman" ID="58" />
<Group Name="MI32_J3D_Jonathan Darbyshire" ID="60" />
<Group Name="MI32_BS_Bobby Sethi" ID="61" />
<Group Name="MI32_DM_Diana Mathers" ID="62" />
<Group Name="MI32_KER_Kerry Redmond" ID="63" />
<Group Name="MI32_MO_Marc Oldland" ID="65" />
</Group>
<Group Name="Director" ID="33">
<Group Name="Director_Client Internal" ID="320" />
<Group Name="Director_Client External" ID="321" />
<Group Name="Director_Net Starters_Finishers" ID="400" />
<Group Name="Director AWR" ID="455" />
<Group Name="Director Board Data_Gareth Owen" ID="488" />
</Group>
<Group Name="Finance" ID="36">
<Group Name="Fin_Net Starters_Finishers" ID="401" />
<Group Name="Fin_Turnover (Unadjusted)" ID="464" />
<Group Name="Fin_Systems Spend" ID="487" />
<Group Name="Fin_Sales Ledger" ID="504" />
</Group>
<Group Name="System Administration" ID="44" />
<Group Name="Account Manager" ID="68">
<Group Name="Account Manager Master" ID="69" />
<Group Name="URS" ID="70" />
<Group Name="Chubb" ID="71" />
<Group Name="Welsh Water" ID="72" />
<Group Name="Thales" ID="74" />
<Group Name="Costain" ID="75" />
<Group Name="Airbus" ID="124" />
</Group>
<Group Name="Branch Administration" ID="330">
<Group Name="MI39_Admin_London Technical" ID="331" />
<Group Name="Branch Administration Master" ID="351" />
<Group Name="MI19_Admin_Science" ID="363" />
<Group Name="MI51_Admin_Oil & Gas London" ID="364" />
<Group Name="MI02_Admin_Aerospace_Preston" ID="367" />
<Group Name="MI02_Admin_Aerospace_South" ID="471" />
<Group Name="MI02_Admin_Aerospace_South_Nicola Leggett" ID="485" />
<Group Name="MO01_Admin_Houston" ID="495" />
</Group>
<Group Name="Payroll" ID="414" />
<Group Name="Business Development" ID="454" />
<Group Name="JC - Work In Progress (JDV)" ID="503" />
<Group Name="JC - Work In Progress (Vencuro)" ID="507" />
<Group Name="Sales Ledger View - Work in Progress" ID="512" />
<Group Name="JC - Work In Progress (Thales)" ID="543" />
</Group>
<Group Name="External" ID="30">
<Group Name="Client" ID="34">
<Group Name="Client Master" ID="54" />
<Group Name="Costain" ID="73" />
</Group>
</Group>
<Group Name="Demo Dashboards" ID="47" />
<Group Name="Master Components" ID="416" />
<Group Name="Demo Designer" ID="531" />
</Group>
</Group>
</Groups>
How can I achieve A treeview with Group Names in hierarchical manner? sample XAML and Class to bind Items would be really helpful. - Programming Language C#
Many thanks in advance.
-Vinnie
First you need to create your class from XML schema like this:
[XmlRoot("Groups")]
public class GroupsXml
{
[XmlElement("Group", typeof(Group))]
public List<Group> GroupsList { get; set; }
}
public class Group
{
[XmlAttribute("ID")]
public int Id { get; set; }
[XmlAttribute("Name")]
public string Name{ get; set; }
}
Then you need to serialize your xml string into list of objects or groups in your case for example:
public List<Group> ReadGroupsFromXmlFile(string fileName)
{
var groupsXml = new GroupsXml();
var groupsXmlFile = xDocument.Load(fileName).ToString();
var groupType = groupsXml .GetType();
var oXmlSerializer = new XmlSerializer(groupType);
groupsXml = (GroupsXml)oXmlSerializer.Deserialize(new StringReader(groupsXmlFile ));
return categoriesXml.GroupsList;
}
I hope it answers your question
Related
perhaps I am going in the wrong direction with this, but any advice would be appreciated. I am trying to develop a small nuget package which can be installed into new .NET Framework Web Apps (MVC) so that new projects can start quicker, quickly adding features such as SSO, Areas, and business logic etc.
This then needs to be extendable so once the package is installed, the routes, areas, and auth can all be built upon.
The package works fine, it can be installed into a new project and all the auth, styling and routes work fine. The problem is these installed features appear to be hidden away within the .dll or the bin of the package, and I'm seemingly not able to edit them.
I tried adding some extra details in the csproj, and/or the .nuspec manifest, to manually pushing the files into the projects file structure. Unfortunately this just seems to create duplicates on top of the files encased in the nugets .dll and causes build errors.
Is it possible to actually have editable .cs files in nuget packages which can be accessed by the user, or am I overstepping the goal of this package?
See below my .nuspec manifest.
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>$id$</id>
<version>1.1</version>
<title>$title$</title>
<authors>$author$</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<!-- <icon>icon.png</icon> -->
<description>$description$</description>
<releaseNotes>Initial Release</releaseNotes>
<copyright>$copyright$</copyright>
<tags>x</tags>
<dependencies>
<group targetFramework=".NETFramework4.8">
<dependency id="Antlr" version="3.5.0.2" />
<dependency id="bootstrap" version="5.1.3" />
<dependency id="jQuery" version="3.6.0" />
<dependency id="jQuery.Validation" version="1.19.4" />
<dependency id="Microsoft.AspNet.Mvc" version="5.2.9" />
<dependency id="Microsoft.AspNet.Razor" version="3.2.9" />
<dependency id="Microsoft.AspNet.Web.Optimization" version="1.1.3" />
<dependency id="Microsoft.AspNet.WebPages" version="3.2.9" />
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="3.6.0" />
<dependency id="Microsoft.IdentityModel.Abstractions" version="6.20.0" />
<dependency id="Microsoft.IdentityModel.JsonWebTokens" version="6.20.0" />
<dependency id="Microsoft.IdentityModel.Logging" version="6.20.0" />
<dependency id="Microsoft.IdentityModel.Protocols" version="6.20.0" />
<dependency id="Microsoft.IdentityModel.Protocols.OpenIdConnect" version="6.20.0" />
<dependency id="Microsoft.IdentityModel.Tokens" version="6.20.0" />
<dependency id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.12" />
<dependency id="Microsoft.Owin" version="4.2.2" />
<dependency id="Microsoft.Owin.Host.SystemWeb" version="4.2.2" />
<dependency id="Microsoft.Owin.Security" version="4.2.2" />
<dependency id="Microsoft.Owin.Security.Cookies" version="4.2.2" />
<dependency id="Microsoft.Owin.Security.OpenIdConnect" version="4.2.2" />
<dependency id="Microsoft.Web.Infrastructure" version="2.0.0" />
<dependency id="Modernizr" version="2.8.3" />
<dependency id="Newtonsoft.Json" version="13.0.1" />
<dependency id="Owin" version="1.0" />
<dependency id="System.IdentityModel.Tokens.Jwt" version="6.20.0" />
<dependency id="WebGrease" version="1.6.0" />
</group>
</dependencies>
</metadata>
<files>
<file src="Areas\Admin\AdminAreaRegistration.cs" target="content\Areas\Admin\" />
<file src="App_Start\Startup.Auth.cs" target="content\App_Start\" />
<file src="Areas\Admin\Controllers\AdmiNController.cs" target="content\Areas\Admin\Controllers\" />
</files>
</package>
I don't think it is possible because NuGets are already COMPILED CODE.
also, NuGet's goal is to package reusable code and really not make them editable.
What you are probably looking for is Source Generators .NET SDK
I'm trying to convert a project in my solution to a nuget package. I threw in a .nuspec that was edited from another nuget package I've created, and all seems to be pointing to the correct stuff. My project clearly has a "target Framework" set under properties to 4.6.2, yet when I run my package to pack I'm getting the 'targetFramework' attribute not declared error. I'll post the logs here if you think it'll help. (Also worth mentioning that I'm doing this through TeamCity's nuget CLI build step)
Here's my sanitized nuspec:
<?xml version="1.0"?>
<package >
<metadata>
<id>PROJECTNAME.WebUI</id>
<version>$version$</version>
<title>PROJECTNAME.WebUI</title>
<authors>COMPANYNAME</authors>
<owners>COMPANYNAME</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>PROJECTNAME.WebUI</description>
<releaseNotes></releaseNotes>
<copyright>Copyright 2018, COMPANYNAME</copyright>
<dependencies>
<dependency id="AntiXSS" version="4.2.1" targetFramework="net462" />
<dependency id="Aspose.Cells" version="8.7.0" targetFramework="net462" />
<dependency id="Aspose.Email" version="6.2.0" targetFramework="net462" />
<dependency id="Aspose.Pdf" version="11.3.0" targetFramework="net462" />
<dependency id="Aspose.Words" version="16.1.0" targetFramework="net462" />
<dependency id="CuteEditor" version="6.7.1.1" targetFramework="net462" />
<dependency id="EO.Pdf" version="15.3.1.0" targetFramework="net462" />
</dependencies>
</metadata>
<files>
</files>
</package>
From the documentation about dependencies.
You can specify multiple targets with this syntax
<?xml version="1.0"?>
<package >
<metadata>
<id>PROJECTNAME.WebUI</id>
<version>$version$</version>
<title>PROJECTNAME.WebUI</title>
<authors>COMPANYNAME</authors>
<owners>COMPANYNAME</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>PROJECTNAME.WebUI</description>
<releaseNotes></releaseNotes>
<copyright>Copyright 2018, COMPANYNAME</copyright>
<dependencies>
<group targetFramework="net462">
<dependency id="AntiXSS" version="4.2.1" />
<dependency id="Aspose.Cells" version="8.7.0" />
<dependency id="Aspose.Email" version="6.2.0" />
<dependency id="Aspose.Pdf" version="11.3.0" />
<dependency id="Aspose.Words" version="16.1.0" />
<dependency id="CuteEditor" version="6.7.1.1" />
<dependency id="EO.Pdf" version="15.3.1.0" />
</group>
</dependencies>
</metadata>
<files>
</files>
</package>
Or, if it is a simple library with no differences among targets, then do not make any reference to the target framework.
<?xml version="1.0"?>
<package >
<metadata>
<id>PROJECTNAME.WebUI</id>
<version>$version$</version>
<title>PROJECTNAME.WebUI</title>
<authors>COMPANYNAME</authors>
<owners>COMPANYNAME</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>PROJECTNAME.WebUI</description>
<releaseNotes></releaseNotes>
<copyright>Copyright 2018, COMPANYNAME</copyright>
<dependencies>
<dependency id="AntiXSS" version="4.2.1" />
<dependency id="Aspose.Cells" version="8.7.0" />
<dependency id="Aspose.Email" version="6.2.0" />
<dependency id="Aspose.Pdf" version="11.3.0" />
<dependency id="Aspose.Words" version="16.1.0" />
<dependency id="CuteEditor" version="6.7.1.1" />
<dependency id="EO.Pdf" version="15.3.1.0" />
</dependencies>
</metadata>
<files>
</files>
</package>
I created the extension for Visual Studio 2015 which looks this
But i want to place all the four menus in a category say My Group. Which should like this.
My Group [On click of this the rest of submenus shoud come same as shown in the image]
menu one
menu two
My vsct file looks like this
<Commands package="package">
<Groups>
<Group guid="PackageCmdSet" id="MenuGroup" priority="0x0300">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_ITEMNODE"/>
</Group>
<Group guid="ClassPackageCmdSet" id="ProjectMenuGroup" priority="0x0400">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PROJNODE"/>
</Group>
</Groups>
and i have buttons like this
<Buttons>
<Button guid="PackageCmdSet" id="BranchModelClassId" priority="0x0100" type="Button" >
<Parent guid="PackageCmdSet" id="MenuGroup" />
<Icon guid="guidImages" id="bmpPic1" />
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<CommandName>Test</CommandName>
<ButtonText>Test</ButtonText>
</Strings>
</Button>
How to created a nested menu which i shouwn in the second image ?
Please help me on this.
I finally figured out the way. The change has to be done in the vsct file.
Add menus first inside the Commands
<Menus>
<Menu guid="PackageCmdSet" id="MainMenu" priority="0x0100" type="Menu">
<Parent guid="PackageCmdSet" id="MenuGroup" />
<Strings>
<ButtonText>Nested Menu</ButtonText>
</Strings>
</Menu>
<Menus>
Then add groups
<Groups>
<Group guid="PackageCmdSet" id="MenuGroup" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_ITEMNODE"/>
</Group>
<Group guid="PackageCmdSet" id="CommandsMenuGruop" priority="0x0300">
<Parent guid="PackageCmdSet" id="MainMenu"/>
</Group>
<Groups>
The button should be like this
<Buttons>
<Button guid="PackageCmdSet" id="ClassId" priority="0x0100" type="Button">
<Parent guid="PackageCmdSet" id="CommandsMenuGruop" />
<Icon guid="guidImages" id="bmpPic1" />
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<CommandName>Command</CommandName>
<ButtonText>Item 1</ButtonText>
</Strings>
</Button>
<Buttons>
I would like to order my XML file, but I'm having troubles in understanding how. I noticed that a lot of suggestions are similar to this case.
var bookstore = xDoc.Element("bookstore")
.Elements("book")
.OrderByDescending(s => (int) s.Attribute("id"));
My XML is made like this:
<?xml version="1.0" encoding="utf-8"?>
<rank>
<difficulty template="gamer">
<car type="FormulaA" />
<car type="FormulaC" />
<car type="GT2" />
<car type="FormulaB" />
</difficulty>
<difficulty template="racer">
<car type="FormulaA" />
<car type="FormulaC" />
<car type="GT2" />
<car type="FormulaB" />
</difficulty>
<difficulty template="pro">
<car type="FormulaA" />
<car type="FormulaC" />
<car type="GT2" />
<car type="FormulaB" />
</difficulty>
</rank>
I would like to modify it so that the final result is similar to this one, then write it again to the same file.
<?xml version="1.0" encoding="utf-8"?>
<rank>
<difficulty template="gamer">
<car type="FormulaA" />
<car type="FormulaB" />
<car type="FormulaC" />
<car type="GT2" />
</difficulty>
<difficulty template="racer">
<car type="FormulaA" />
<car type="FormulaB" />
<car type="FormulaC" />
<car type="GT2" />
</difficulty>
<difficulty template="pro">
<car type="FormulaA" />
<car type="FormulaB" />
<car type="FormulaC" />
<car type="GT2" />
</difficulty>
</rank>
I tried to sort those elements with this code, but it doesn't give me the result I want.
XDocument xDoc = XDocument.Load(xmlFile);
var orderedXmlFile = xDoc.Descendants("car").OrderBy(s => (string)s.Attribute("type"));
XDocument doc = new XDocument(new XElement("rank"), orderedXmlFile);
doc.Save(xmlFile);
orderedXmlFile becomes a list similar to
<car type="FormulaA" />
<car type="FormulaA" />
<car type="FormulaA" />
<car type="FormulaB" />
<car type="FormulaB" />
<car type="FormulaB" />
<car type="GT2" />
<car type="GT2" />
<car type="GT2" />
and then I'm unable to save the file. This is the first time I'm trying to modify xml files in C#, so I'll gladly take any advice or suggestions you'd want to give me.
You're not really trying to order all the car elements - you're trying to order each group of elements. It's probably simplest just to use ReplaceNodes for each difficulty element:
foreach (var difficulty in xDoc.Root.Elements("difficulty"))
{
difficulty.ReplaceNodes(difficulty.Elements()
.OrderBy(x => (string) x.Attribute("type")));
}
Then just save xDoc again.
This assumes you don't mind modifying your existing XDocument, of course.
I am trying to make it so that when the user selects something via check box, a corresponding feature will be installed.
I am aware of the prebuilt feature tree that Wix provides but there are some other things that I am doing that do not allow me to use this function. I am curious as to how to link the two together so that when the user selects the check box "Install Feature X", feature X is installed when the user clicks the install button.
I found what it was that solves my issue. To do as I had intended, I needed to create a checkbox for each feature as so.
<Control Id="FeatureX" Type="CheckBox" X="191" Y="50" Width="140" Height="17"
Property="FEATUREX_CHECKED" CheckBoxValue="myValue" Text="Install feature X" />
<Control Id="FeatureY" Type="CheckBox" X="191" Y="67" Width="140" Height="17"
Property="FEATUREY_CHECKED" CheckBoxValue="myValue" Text="Install feature Y" />
<Control Id="FeatureZ" Type="CheckBox" X="191" Y="84" Width="140" Height="17"
Property="FEATUREZ_CHECKED" CheckBoxValue="myValue" Text="Install feature Z" />
Now once I did that I then added a corresponding publish to each, and made a condition that made it so that only if the check box is selected will that feature be installed. Like so:
<Control Id="Next" Type="PushButton" Text="Next" X="254" Y="243" Height="17" Width="56">
<Publish Event="Remove" Value="ALL" Order="1">1</Publish>
<Publish Event="AddLocal" Value="FeatureX" Order="2">
<![CDATA[FEATUREX_CHECKED]]>
</Publish>
</Control>
NOTE:
Remove is used to deselect everything from being installed (It was brought to my attention that once the UI is invoked, it is too late to change feature levels).
Then each feature is checked to see if the "corresponding checkbox" has been selected and if so adds it to the "AddLocal" Property. AddLocal would look like this if one were to look at it:
ADDLOCAL=FeatureX, FeatureY, FeatureZ...
The final thing I needed to do to get this to work was too check in my main.wxs to make sure that the FeatureID used in the checkboxes matched up with the ComponentGroupRefID used:
<ComponentGroupRef Id="FeatureX"/>
So there it is...
I again, thank everyone for their help with this. If anyone reading this is confused by anything, please feel free to drop me a line, and I will do my best to explain things a little bit further.
This is my sample code for installing features
Product.wxs
<Product Id="{C9FD5DDE-2625-4E01-B415-8A734464F341}"
Name="!(wix.Product)" Language="1033" Version="1.0.0.0"
Manufacturer="!(wix.Manufacturer)" UpgradeCode="!(wix.UpgradeCode)">
<Package InstallerVersion="200" Compressed="yes" Languages="1033"
Manufacturer="!(wix.Manufacturer)" Description="!(wix.ProductDesc)"/>
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<WixVariable Id="UpgradeCode" Value="{E5695E2A-EE5F-4EEE-A326-98A9F8B2EF0A}"/>
<WixVariable Id="Manufacturer" Value="BSDreams"/>
<WixVariable Id="Product" Value="WixSubFeatures"/>
<WixVariable Id="ProductDesc" Value="Minimal select one feature install"/>
<WixVariable Id="ProductIcon" Value="chk_on.ico"/>
<WixVariable Id="WixSubFiles" Value=".\Files"/>
<Property Id="ARPNOMODIFY" Value="0" />
<Property Id="ARPPRODUCTICON" Value="!(wix.ProductIcon)" />
<Property Id="INSTALLDIR">
<RegistrySearch Id="WixSubFeaturesSearch" Type="raw" Root="HKCU"
Key="!(wix.Manufacturer)\!(wix.Product)" Name="InstallDir" />
</Property>
<Icon Id="chk_on.ico" SourceFile="!(wix.WixSubFiles)\!(wix.ProductIcon)"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ManufacturerDir" Name="!(wix.Manufacturer)">
<Directory Id="INSTALLDIR" Name="!(wix.Product)">
<Component Id="ProductMain" Guid="{FF35C142-480A-4d67-A2ED-E5C9E508F809}">
<CreateFolder />
<RegistryKey Id="WixSubDirReg" Root="HKCU" Key="!(wix.Manufacturer)\!(wix.Product)" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Value="[INSTALLDIR]" Action="write"/>
</RegistryKey>
</Component>
</Directory>
</Directory>
</Directory>
<UIRef Id="UserInterface"/>
<Feature Id="PRODUCTFEATURE" Title="!(wix.Product)" Level="1" >
<ComponentRef Id="ProductMain"/>
<ComponentRef Id="IconFile"/>
<Feature Id="OPTIONA" Title="Option A" Level="1" >
<ComponentRef Id="TestFileA"/>
</Feature>
<Feature Id="OPTIONB" Title="Option B" Level="3" >
<ComponentRef Id="TestFileB"/>
</Feature>
<Feature Id="OPTIONC" Title="Option C" Level="3" >
<ComponentRef Id="TestFileC"/>
</Feature>
</Feature>
<DirectoryRef Id="INSTALLDIR">
<Component Id="IconFile" Guid="{967A5110-B0F8-47b0-967B-CC4624D06EA5}">
<File Id="IconFileA" Source="!(wix.WixSubFiles)\!(wix.ProductIcon)" Name="chk_on.ico" Vital="yes" />
</Component>
<Component Id="TestFileA" Guid="{F5ACE3D7-03DE-47a7-9CE8-50CEF5E9A7BF}">
<File Id="SomeFileA" Source="!(wix.WixSubFiles)\SomeFileA.txt" Name="BSDA.txt" Vital="yes"/>
</Component>
<Component Id="TestFileB" Guid="{CB5D53FB-8CED-42ef-89FF-08C7709CFCA5}">
<File Id="SomeFileB" Source="!(wix.WixSubFiles)\SomeFileB.txt" Name="BSDB.txt" Vital="yes" />
</Component>
<Component Id="TestFileC" Guid="{987EA193-A1E0-41d2-8E9D-87D30D8F03AD}">
<File Id="SomeFileC" Source="!(wix.WixSubFiles)\SomeFileC.txt" Name="BSDC.txt" Vital="yes" />
</Component>
</DirectoryRef>
<CustomAction Id="SetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
<InstallExecuteSequence>
<Custom Action="SetARPINSTALLLOCATION" After="InstallValidate"></Custom>
</InstallExecuteSequence>
</Product>
UserInterface.wxs
<Fragment Id="WixSubUI">
<UI Id="UserInterface">
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
<Property Id="WixUI_Mode" Value="Custom" />
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="9" Bold="yes" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="FatalError" />
<DialogRef Id="UserExit" />
<DialogRef Id="InstallDirDlg"/>
<DialogRef Id="FeaturesDlg" />
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="FeaturesDlg" Order="2"></Publish>
<Publish Dialog="FeaturesDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="FeaturesDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="ExitDialog" Order="2">1</Publish>
<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
</UI>
<UIRef Id="WixUI_Common" />
This will give you a basic installer that installs base on the selected features checkbox UI
The advice for check boxes is eerily similar to that for radio buttons. Use AddLocal and Remove control events on the Next or Install button, each of which condition against the property tied to your check boxes. It's too late to use feature install levels by the time you're showing UI to the user.