I am developping a windows 8.1 application and since few days I am struggling with a problem.
Here is my probem:
I have a tfs project and via my application I want to follow it (displaying the state, created by, changed by,etc) using tfs odata.
Here is the xml file obtained :
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="https://tfsodata.visualstudio.com/DefaultCollection/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<title type="text">WorkItems</title>
<id>https://tfsodata.visualstudio.com/DefaultCollection/Projects('project1')/WorkItems/</id>
<updated>2014-05-02T14:52:17Z</updated>
<link rel="self" title="WorkItems" href="WorkItems" />
<entry m:etag="W/"datetime'2014-03-12T19%3A54%3A38.193%2B00%3A00'"">
<id>https://tfsodata.visualstudio.com/DefaultCollection/WorkItems(1)</id>
<title type="text">ProjetTest</title>
<summary type="text"></summary>
<updated>2014-03-12T19:54:38Z</updated>
<author>
<name />
</author>
<link rel="edit" title="WorkItem" href="WorkItems(1)" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Attachments" type="application/atom+xml;type=feed" title="Attachments" href="WorkItems(1)/Attachments" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Links" type="application/atom+xml;type=feed" title="Links" href="WorkItems(1)/Links" />
<category term="Microsoft.Samples.DPE.ODataTFS.Model.Entities.WorkItem" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">1</d:Id>
<d:Project>project1</d:Project>
<d:Type>Product Backlog Item</d:Type>
<d:WebEditorUrl>https://xxxx.visualstudio.com/web/wi.aspx?pcguid=f2ba9200-f167-43e8-a92e-d36b1bc1b561&id=1</d:WebEditorUrl>
<d:AreaPath>ptoject1</d:AreaPath>
<d:IterationPath>project1</d:IterationPath>
<d:Revision m:type="Edm.Int32">2</d:Revision>
<d:Priority m:null="true" />
<d:Severity m:null="true" />
<d:StackRank m:type="Edm.Double">0</d:StackRank>
<d:AssignedTo></d:AssignedTo>
<d:CreatedDate m:type="Edm.DateTime">2014-03-12T19:54:25.783+00:00</d:CreatedDate>
<d:CreatedBy>xxxxx</d:CreatedBy>
<d:ChangedDate m:type="Edm.DateTime">2014-03-12T19:54:38.193+00:00</d:ChangedDate>
<d:ChangedBy>xxxxx</d:ChangedBy>
<d:ResolvedBy m:null="true" />
<d:Title>ProjetTest</d:Title>
<d:State>New</d:State>
<d:Reason>New backlog item</d:Reason>
<d:CompletedWork m:type="Edm.Double">0</d:CompletedWork>
<d:RemainingWork m:type="Edm.Double">0</d:RemainingWork>
<d:Description></d:Description>
<d:ReproSteps m:null="true" />
<d:FoundInBuild m:null="true" />
<d:IntegratedInBuild></d:IntegratedInBuild>
<d:AttachedFileCount m:type="Edm.Int32">0</d:AttachedFileCount>
<d:HyperLinkCount m:type="Edm.Int32">0</d:HyperLinkCount>
<d:RelatedLinkCount m:type="Edm.Int32">0</d:RelatedLinkCount>
<d:Risk m:null="true" />
<d:StoryPoints m:type="Edm.Double">0</d:StoryPoints>
<d:OriginalEstimate m:type="Edm.Double">0</d:OriginalEstimate>
<d:BacklogPriority m:type="Edm.Double">1000000000</d:BacklogPriority>
<d:BusinessValue m:type="Edm.Int32">0</d:BusinessValue>
<d:Effort m:type="Edm.Double">0</d:Effort>
<d:Blocked m:null="true" />
<d:Size m:type="Edm.Double">0</d:Size>
</m:properties>
</content>
</entry>
<entry m:etag="W/"datetime'2014-03-24T12%3A07%3A56.397%2B00%3A00'"">
<id>https://tfsodata.visualstudio.com/DefaultCollection/WorkItems(2)</id>
<title type="text">test2</title>
<summary type="text"></summary>
<updated>2014-03-24T12:07:56Z</updated>
<author>
<name />
</author>
<link rel="edit" title="WorkItem" href="WorkItems(2)" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Attachments" type="application/atom+xml;type=feed" title="Attachments" href="WorkItems(2)/Attachments" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Links" type="application/atom+xml;type=feed" title="Links" href="WorkItems(2)/Links" />
<category term="Microsoft.Samples.DPE.ODataTFS.Model.Entities.WorkItem" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">2</d:Id>
<d:Project>project1</d:Project>
<d:Type>Product Backlog Item</d:Type>
<d:WebEditorUrl>https://xxxxx.visualstudio.com/web/wi.aspx?pcguid=f2ba9200-f167-43e8-a92e-d36b1bc1b561&id=2</d:WebEditorUrl>
<d:AreaPath>project1</d:AreaPath>
<d:IterationPath>project1</d:IterationPath>
<d:Revision m:type="Edm.Int32">4</d:Revision>
<d:Priority m:null="true" />
<d:Severity m:null="true" />
<d:StackRank m:type="Edm.Double">0</d:StackRank>
<d:AssignedTo></d:AssignedTo>
<d:CreatedDate m:type="Edm.DateTime">2014-03-12T20:16:49.827+00:00</d:CreatedDate>
<d:CreatedBy>xxxx</d:CreatedBy>
<d:ChangedDate m:type="Edm.DateTime">2014-03-24T12:07:56.397+00:00</d:ChangedDate>
<d:ChangedBy>xxxx</d:ChangedBy>
<d:ResolvedBy m:null="true" />
<d:Title>test2</d:Title>
<d:State>Committed</d:State>
<d:Reason>Additional work found</d:Reason>
<d:CompletedWork m:type="Edm.Double">0</d:CompletedWork>
<d:RemainingWork m:type="Edm.Double">0</d:RemainingWork>
<d:Description></d:Description>
<d:ReproSteps m:null="true" />
<d:FoundInBuild m:null="true" />
<d:IntegratedInBuild></d:IntegratedInBuild>
<d:AttachedFileCount m:type="Edm.Int32">0</d:AttachedFileCount>
<d:HyperLinkCount m:type="Edm.Int32">0</d:HyperLinkCount>
<d:RelatedLinkCount m:type="Edm.Int32">0</d:RelatedLinkCount>
<d:Risk m:null="true" />
<d:StoryPoints m:type="Edm.Double">0</d:StoryPoints>
<d:OriginalEstimate m:type="Edm.Double">0</d:OriginalEstimate>
<d:BacklogPriority m:type="Edm.Double">999968378</d:BacklogPriority>
<d:BusinessValue m:type="Edm.Int32">0</d:BusinessValue>
<d:Effort m:type="Edm.Double">0</d:Effort>
<d:Blocked m:null="true" />
<d:Size m:type="Edm.Double">0</d:Size>
</m:properties>
</content>
</entry>
</feed>
my class:
paste special as xml classes (from the xml above)
my function :
public IEnumerable<TfsEntitiesXml.feed> Deserialize()
{
string xml = "https://tfsodata.visualstudio.com/DefaultCollection/Projects('xxxx')/WorkItems".Trim();
XmlSerializer serilaizer = new XmlSerializer(typeof(TfsEntitiesXml.feed));
//string xml = "";
byte[] buffer = Encoding.UTF8.GetBytes(xml);
var stream = new MemoryStream();
stream.WriteAsync(buffer, 0, buffer.Length);
IEnumerable<TfsEntitiesXml.feed> result = (IEnumerable<TfsEntitiesXml.feed>)serilaizer.Deserialize(stream);
return result;
}
and the xaml
<ListView x:Name="itemsListView"
SelectionMode="None"
ItemsSource="{Binding TfsList}" >
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock
Foreground=
"{StaticResource ListViewItemOverlayForegroundThemeBrush}"
Style="{StaticResource TitleTextStyle}" Height="60"
TextWrapping="Wrap"
Margin="15,5,15,0">
<Run Text="{Binding Title}" ></Run>
<Run Text="{Binding State}" ></Run>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
var projects = tfsConnector.Deserialize();
DefaultViewModel["TfsList"] = projects;
When I run I get this exception
An exception of type 'System.InvalidOperationException' occurred in System.Xml.dll but was not handled in user code
Additional information: There is an error in XML document (0, 0).
I am struggling with this problem since few days now.
Can someone help me please?
Thank you
You should simply make a service reference to the tfsodata service, this way you will get a typed reference and don't have to mess with the xml.
See this blogpost
Related
For an Outlook Add-In I created a Blacklist in a XML File. Now I need to save the words which are in my Blacklist in an string array to create a if-else condition. This is what I tried but it doesn't work...
private string[] XMLReader()
{
string[] arr = XDocument.Load(#"C:\ProjektOutlook\outlookadresses\Add-In\Add-In\Resources\Blacklist.xml").Descendants("attachmentRefs")
.Select(Name => Name.Value).ToArray();
return arr;
}
This is what my XML File looks like:
<?xml version="1.0" encoding="utf-8" ?>
<blacklist>
<attachmentRefs>
<attachmentRef Name="Anhang" />
<attachmentRef Name="anhang" />
<attachmentRef Name="Anlage" />
<attachmentRef Name="anlage" />
<attachmentRef Name="Angefügt" />
<attachmentRef Name="angefügt" />
<attachmentRef Name="Anahng" />
<attachmentRef Name="angehängt" />
<attachmentRef Name="Angehängt" />
<attachmentRef Name="angehangen" />
<attachmentRef Name="Angehangen" />
<attachmentRef Name="anahng" />
<attachmentRef Name="Analge" />
<attachmentRef Name="analge" />
<attachmentRef Name="Anliegend" />
<attachmentRef Name="anliegend" />
<attachmentRef Name="Beigefügt" />
<attachmentRef Name="beigefügt" />
<attachmentRef Name="beiliegend" />
<attachmentRef Name="Beiliegend" />
<attachmentRef Name="hinzugefügt" />
<attachmentRef Name="Datei" />
<attachmentRef Name="Dokument" />
<attachmentRef Name="Beischrift" />
<attachmentRef Name="Ergänzung" />
<attachmentRef Name="Nachtrag" />
<attachmentRef Name="Zusatz" />
<attachmentRef Name="Beilage" />
<attachmentRef Name="Addendum" />
</attachmentRefs>
</blacklist>
I need the app to be able to list jpg files from folder "Photos".
I am stuck on reading jpg files from sd card on windows phone device.
What is done in order to resolve the problem:
created function to read files into collection. The function was
taken from basic sample called "RouteMapper"
ListBox to holding the list of files
permission to use sd card and jpg files
Function:
Photos = new ObservableCollection<ExternalStorageFile>();
private async void scanExternalStorage_Run()
{
// Clear the collection bound to the page.
Photos.Clear();
// Connect to the current SD card.
ExternalStorageDevice _sdCard = (await ExternalStorage.GetExternalStorageDevicesAsync()).FirstOrDefault();
// If the SD card is present, add GPX files to the Routes collection.
if (_sdCard != null)
{
try
{
// Look for a folder on the SD card named Routes.
ExternalStorageFolder photosFolder = await _sdCard.GetFolderAsync("Photos");
// Get all files from the Routes folder.
IEnumerable<ExternalStorageFile> photosFiles = await photosFolder.GetFilesAsync();
// Add each GPX file to the Routes collection.
foreach (ExternalStorageFile esf in photosFiles)
{
if (esf.Path.EndsWith(".jpg"))
{
Photos.Add(esf);
}
}
}
catch (FileNotFoundException)
{
// No Routes folder is present.
MessageBox.Show("The Routes folder is missing on your SD card. Add a Routes folder containing at least one .GPX file and try again.");
}
}
else
{
// No SD card is present.
MessageBox.Show("The SD card is mssing. Insert an SD card that has a Routes folder containing at least one .GPX file and try again.");
}
}
ListBox:
<ListBox
x:Name="jpgFilesListBox"
ItemsSource="{Binding Photos}"
SelectionChanged="jpgFilesListBox_SelectionChanged"
>
<!-- Each ListBox item is bound to the name of each GPX file -->
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock
Margin="0, 12, 0, 0"
Text="{Binding Name}"
Style="{StaticResource PhoneTextTitle2Style}"
/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
WMAppManifest.xml:
<Capabilities>
<Capability Name="ID_CAP_NETWORKING" />
<Capability Name="ID_CAP_MEDIALIB_AUDIO" />
<Capability Name="ID_CAP_MEDIALIB_PLAYBACK" />
<Capability Name="ID_CAP_SENSORS" />
<Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
<Capability Name="ID_CAP_REMOVABLE_STORAGE" />
<Capability Name="ID_CAP_MAP" />
</Capabilities>
<Extensions>
<FileTypeAssociation TaskID="_default" Name="JPG" NavUriFragment="fileToken=%s">
<SupportedFileTypes>
<FileType ContentType="application/jpg">.jpg</FileType>
</SupportedFileTypes>
</FileTypeAssociation>
</Extensions>
Debugging revealed photosFolder.GetFilesAsync() returns 0.
While I definately have files in the "Photos" folder.
RouteMapper works fine and returns list of gpx files.
PS: I use emulator 8.1
Update: just for information. GetFolderAsync works and returns object that contains "D:\Photos"
Update2: Adding manifest files. I've got two of them after creating clean Windows Phone SilverLight blank App.
WMAppManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2014/deployment" AppPlatformVersion="8.1">
<DefaultLanguage xmlns="" code="en-US" />
<App xmlns="" ProductID="{dc1cb15e-1c8d-4635-a85e-e414e89455fb}" Title="CameraGPS" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal" Author="CameraGPS author" Description="Sample description" SDOptOut="false" BackUpOptOut="false" Publisher="CameraGPS" PublisherID="{4d13b339-1a9f-4a55-ba44-fe10cf0c0420}">
<IconPath IsRelative="true" IsResource="false">Assets\ApplicationIcon.png</IconPath>
<Capabilities>
<Capability Name="ID_CAP_NETWORKING" />
<Capability Name="ID_CAP_MEDIALIB_AUDIO" />
<Capability Name="ID_CAP_MEDIALIB_PLAYBACK" />
<Capability Name="ID_CAP_SENSORS" />
<Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
<Capability Name="ID_CAP_REMOVABLE_STORAGE" />
<Capability Name="ID_CAP_MAP" />
<Capability Name="ID_CAP_MEDIALIB_PHOTO" />
</Capabilities>
<Tasks>
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" ActivationPolicy="Resume" />
</Tasks>
<Tokens>
<PrimaryToken TokenID="CameraGPSToken" TaskName="_default">
<TemplateFlip>
<SmallImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileSmall.png</SmallImageURI>
<Count>0</Count>
<BackgroundImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileMedium.png</BackgroundImageURI>
<Title>CameraGPS</Title>
<BackContent>
</BackContent>
<BackBackgroundImageURI>
</BackBackgroundImageURI>
<BackTitle>
</BackTitle>
<DeviceLockImageURI>
</DeviceLockImageURI>
<HasLarge>
</HasLarge>
</TemplateFlip>
</PrimaryToken>
</Tokens>
<Extensions>
<FileTypeAssociation TaskID="_default" Name="jpg" NavUriFragment="fileToken=%s">
<SupportedFileTypes>
<FileType ContentType="image/jpg">.jpg</FileType>
</SupportedFileTypes>
</FileTypeAssociation>
</Extensions>
<ScreenResolutions>
<ScreenResolution Name="ID_RESOLUTION_WVGA" />
<ScreenResolution Name="ID_RESOLUTION_WXGA" />
<ScreenResolution Name="ID_RESOLUTION_HD720P" />
</ScreenResolutions>
</App>
</Deployment>
Package.appxmanifest:
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest" xmlns:m3="http://schemas.microsoft.com/appx/2014/manifest" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
<Identity Name="5b897434-732a-4f41-a110-db75375561c9" Publisher="CN=Qet" Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="dc1cb15e-1c8d-4635-a85e-e414e89455fb" PhonePublisherId="4d13b339-1a9f-4a55-ba44-fe10cf0c0420" />
<Properties>
<DisplayName>CameraGPS</DisplayName>
<PublisherDisplayName>Qet</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Prerequisites>
<OSMinVersion>6.3.1</OSMinVersion>
<OSMaxVersionTested>6.3.1</OSMaxVersionTested>
</Prerequisites>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="App" Executable="AGHost.exe" EntryPoint="MainPage.xaml">
<m3:VisualElements DisplayName="CameraGPS" Square150x150Logo="Assets\SquareTile150x150.png" Square44x44Logo="Assets\Logo.png" Description="CameraGPS" ForegroundText="light" BackgroundColor="#464646">
<m3:DefaultTile Square71x71Logo="Assets\SquareTile71x71.png">
</m3:DefaultTile>
<m3:SplashScreen Image="Assets\SplashScreen.png" />
</m3:VisualElements>
<Extensions>
<Extension Category="windows.fileTypeAssociation">
<FileTypeAssociation Name="jpg">
<DisplayName>Jpg</DisplayName>
<SupportedFileTypes>
<FileType ContentType="image/jpg">.jpg</FileType>
</SupportedFileTypes>
</FileTypeAssociation>
</Extension>
<Extension Category="windows.accountPictureProvider" />
<Extension Category="windows.backgroundTasks" EntryPoint="AgHost.BackgroundTask">
<BackgroundTasks>
<Task Type="systemEvent" />
<m2:Task Type="location" />
</BackgroundTasks>
</Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="removableStorage" />
<Capability Name="picturesLibrary" />
<DeviceCapability Name="location" />
<DeviceCapability Name="webcam" />
</Capabilities>
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>AgHostSvcs.dll</Path>
<ActivatableClass ActivatableClassId="AgHost.BackgroundTask" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
</Package>
Added a Database and an Entity Model to my DAL Project.
got an error :
Error :
+ base {"Schema specified is not valid. Errors: \r\nMultiple types with the name 'TblRecord' exist in the EdmItemCollection in different namespaces. Convention based mapping requires unique names without regard to namespace in the EdmItemCollection."} System.Data.EntityException {System.Data.MetadataException}
The Edmx File
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="Xz.Business.Matches.Store" Alias="Self" Provider="System.Data.SqlServerCe.4.0" ProviderManifestToken="4.0" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
<EntityContainer Name="XzBusinessMatchesStoreContainer">
<EntitySet Name="Records" EntityType="Xz.Business.Matches.Store.Records" store:Type="Tables" />
</EntityContainer>
<EntityType Name="Records">
<Key>
<PropertyRef Name="Record" />
</Key>
<Property Name="Record" Type="nvarchar" Nullable="false" MaxLength="100" />
<Property Name="Relations" Type="nvarchar" MaxLength="450" />
</EntityType>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="Xz.Business.Matches" Alias="Self" p1:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns:p1="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityContainer Name="RecordzEntities" p1:LazyLoadingEnabled="true">
<EntitySet Name="Records" EntityType="Xz.Business.Matches.TblRecord" />
</EntityContainer>
<EntityType Name="TblRecord">
<Key>
<PropertyRef Name="Record" />
</Key>
<Property Name="Record" Type="String" Nullable="false" MaxLength="100" Unicode="true" FixedLength="false" />
<Property Name="Relations" Type="String" MaxLength="450" Unicode="true" FixedLength="false" />
</EntityType>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
<EntityContainerMapping StorageEntityContainer="XzBusinessMatchesStoreContainer" CdmEntityContainer="RecordzEntities">
<EntitySetMapping Name="Records">
<EntityTypeMapping TypeName="Xz.Business.Matches.TblRecord">
<MappingFragment StoreEntitySet="Records">
<ScalarProperty Name="Record" ColumnName="Record" />
<ScalarProperty Name="Relations" ColumnName="Relations" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
<Designer xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
<Connection>
<DesignerInfoPropertySet>
<DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
</DesignerInfoPropertySet>
</Connection>
<Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild" Value="true" />
<DesignerProperty Name="EnablePluralization" Value="True" />
<DesignerProperty Name="IncludeForeignKeysInModel" Value="True" />
<DesignerProperty Name="CodeGenerationStrategy" Value="None" />
</DesignerInfoPropertySet>
</Options>
<!-- Diagram content (shape and connector positions) -->
<Diagrams></Diagrams>
</Designer>
</edmx:Edmx>
Names & Namespaces :
Project Name : Business.Matches
Default Namespace : Xz.Business.Matches
I added an Entity Model with this definitions :
Model : RecordzModel
Context : RecordzContext
Model Namespace : Xz.Business.Matches
You seem to have more than one class in your project that is called 'TblRecord'. Namespaces are ignored when matching your types to EDM types for POCO types and therefore if you have more than one class with the same name it is ambiguous and causes the exception.
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.
I have the following structure to XML file:
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property/>
<Property/>
</Control>
<Control id="GroupHeading2">
<Property/>
<Control id="TextBox">
<Property/>
<Property/>
</Control>
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
I am trying to deserialize this into C# object, but I don't need to preserve the hierarchy (which is making it difficult for me to deserialize).
Is there XSL that can transform this to un-nest the Controls, and if possible add an attribute to any child Control with ParentId=""?
Thank you for any guidance!
Given XML, the XmlSerializer can produce a graph of objects that hold the same instance data.
This is known as XML de-serialization
You need to look here :
Using the XmlSerializer Attributes
Serialization and Deserialization in ASP.NET with C#
This template should get you started. I ran it against .NET 2.0.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="#*"/>
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
<xsl:template match="Form">
<Form>
<xsl:copy-of select="#*"/>
<xsl:apply-templates select="//Control"/>
</Form>
</xsl:template>
<xsl:template match="Control">
<Control>
<xsl:if test="ancestor::Control/#id">
<xsl:attribute name="ParentID"><xsl:value-of select="ancestor::Control/#id"/></xsl:attribute>
</xsl:if>
<xsl:copy-of select="*|#*"/>
</Control>
</xsl:template>
</xsl:stylesheet>
This is the output (indented for readability).
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property />
<Property />
</Control>
<Control id="GroupHeading2">
<Property />
<Control id="TextBox">
<Property />
<Property />
</Control>
</Control>
<Control ParentID="GroupHeading2" id="TextBox">
<Property />
<Property />
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
The following stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<!-- first-level control elements -->
<xsl:template match="Control">
<Control>
<xsl:copy-of select="#*|*[not(self::Control)]" />
</Control>
<xsl:apply-templates select="Control" />
</xsl:template>
<!-- nested control elements -->
<xsl:template match="Control/Control">
<Control ParentId="{../#id}">
<xsl:copy-of select="#*|*[not(self::Control)]" />
</Control>
<xsl:apply-templates select="Control" />
</xsl:template>
</xsl:stylesheet>
Applied to the following document (same as original with one additional level of nesting for demonstration purposes):
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property />
<Property />
</Control>
<Control id="GroupHeading2">
<Property />
<Control id="TextBox">
<Property />
<Property />
<Control id="Grandchild">
<Property />
</Control>
</Control>
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
Produces an output with no nested <Control> elements:
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property />
<Property />
</Control>
<Control id="GroupHeading2">
<Property />
</Control>
<Control ParentId="GroupHeading2" id="TextBox">
<Property />
<Property />
</Control>
<Control ParentId="TextBox" id="Grandchild">
<Property />
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>