Happy holidays!

2014 is slowly coming to an end, and we wanted to take the chance and say THANK YOU to all our loyal blog-readers.

The year 2014 was an extraordinary one. There have never been more blogposts, blog-readers, and comments. In the next year, we will bring you more helpful tips and tools for Data Standard, PowerShell, powerJobs, powerGate, Inventor apps, and there are also more new interesing topics to come.

For those of you, who are not solely interested in the deep-tech stuff, but also in more high level info, we launched a newsfeed on our website, where we post all sorts of interesting information about new products, completed projects, customer case studies, promotions and so on.

Click on our christmas tree and check it out! Merry Christmas!

 

christmastree

Posted in Uncategorized | Leave a comment

Summary from the AU Data Standard session

AU2014

Last week, I had the pleasure to meet you at the Autodesk University in Las Vegas. Thanks for the good talk and great feedback. The session around Data Standard introduction was well attended and the ratings were great – beyond 9.3 – THANK YOU for that!

In the short time I tried to give you an overview on what Data Standard is and gave you several examples on how Data Standard can be customised in order to achieve interesting Vault improvements. Although the material is available on the AU page, I’d like to make the presentation and the customisations available here. Some of the topics covered during the session have already been posted on this blog. The other topics will be posted in the next weeks with additional information on how they work.

So, have fun with the Data Standard introduction presentation and the DataStandard samples. I hope with these topics, we are able to engage your imagination of what could be done with Vault. If you have further ideas we should blog on, just leave a comment.

Posted in Data Standard, PowerShell, Vault API | Leave a comment

Password protected PDF

A customer asked us if it is possible to create a password protected PDF with powerJobs. The answer is YES, it is!

Here is the PowerShell code for protecting a PDF file with a password:

[System.Reflection.Assembly]::LoadFrom("itextsharp.dll")

function PSUsing {
 param (
 [System.IDisposable] $inputObject = $(throw "The parameter -inputObject is required."),
 [ScriptBlock] $scriptBlock = $(throw "The parameter -scriptBlock is required.")
 )
 
 Try {
 &$scriptBlock
 }
 Finally {
 if ($inputObject.psbase -eq $null) {
 $inputObject.Dispose()
 } else {
 $inputObject.psbase.Dispose()
 }
 }
}

$file = New-Object System.IO.FileInfo "C:\Temp\test.pdf"
$fileWithPassword = New-Object System.IO.FileInfo "C:\Temp\test_password.pdf"
$password = "secret"
PSUsing ( $fileStreamIn = $file.OpenRead() ) { 
 PSUsing ( $fileStreamOut = New-Object System.IO.FileStream($fileWithPassword.FullName,[System.IO.FileMode]::Create,[System.IO.FileAccess]::Write,[System.IO.FileShare]::None) ) { 
 PSUsing ( $reader = New-Object iTextSharp.text.pdf.PdfReader $fileStreamIn ) {
 [iTextSharp.text.pdf.PdfEncryptor]::Encrypt($reader, $fileStreamOut, $true, $password, $password, [iTextSharp.text.pdf.PdfWriter]::ALLOW_PRINTING)
 }
 }
}

You can see, we are using iTextSharp for doing this. Please download the library from here and extract the content of itextsharp-dll-core.zip to the folder where you will place your powerShell script later.

The file that you specify for $file variable will be stored with password-protection to the file $fileWithPassword.

Just run the script and open the new file with any PDF viewer and you should get this:

04-12-2014 10-03-34

Bam! That’s all. Have fun!

Posted in powerJobs, PowerShell, Uncategorized, Vault API | Leave a comment

Select Vault items from within CAD

itemSelection

How would it be to select an item from Vault directly within Inventor? Yes, I’m in an Inventor model or drawing and via the Data Standard dialog I can pick an existing item from within Vault. Once again, we do this with Data Standard. So, we add an additional tab to the Inventor or AutoCAD Data Standard dialog and either at save or later, the user can place a search onto the Vault items and then select one of the resulting items. The item number will be stored into the Part Number within the Inventor file.

SelectItem

Once the file is checked in, as the part number matches with an existing item, at the assign-item operation, the association will be automatically done.

The customization for this sample involves 2 files. The Inventor.XAML and a new PS1 file. The XAML file has been enhanced with an additional tab and the according search TextBox and a DataGrid for the results. Here the XAML code for the Item tab:

<TabItem Header="Items" HorizontalAlignment="Left" Height="20" VerticalAlignment="Top" Width="55">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="auto"/>
      <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition Width="auto"/>
      </Grid.ColumnDefinitions>
      <TextBox x:Name="SearchText" Grid.Column="0"/>
      <Button Grid.Column="1" Content="Search" Margin="5,0,0,0" Command="{Binding PsCmd[SearchItem]}" CommandParameter="{Binding Text, ElementName=SearchText}"/>
    </Grid>
    <DataGrid Grid.Row="1" x:Name="ItemsFound" AutoGenerateColumns="True" IsReadOnly="True" ColumnWidth="Auto" HorizontalGridLinesBrush="WhiteSmoke" VerticalGridLinesBrush="WhiteSmoke">
      <DataGrid.ContextMenu>
        <ContextMenu>
          <MenuItem Command="{Binding PsCmd[SelectItem]}" Header="Select item" CommandParameter="{Binding SelectedIndex, ElementName=ItemsFound}"/>
        </ContextMenu>
      </DataGrid.ContextMenu>
    </DataGrid>
  </Grid>
</TabItem>

As you can see the Button for the search is bound to a PowerShell function called SelectItem. The entered search text is passed as a CommandParameter to the Button. The DataGrid is somewhat simple as we use the AutoGenerateColumns in order to get the appropriate columns. You’ll notice that we defined a little context menu for the DataGrid. So the user will be able to fire the “Select Item” command.

Let’s have a look to the PowerShell file:

Add-Type @"
public class itemData
{
  public string Item {get;set;}
  public string Revision {get;set;}
  public string Title {get;set;}
}
"@

function SearchItem()
{
  if($mvparam -eq '') { return }
  $srchconds = New-Object autodesk.Connectivity.WebServices.SrchCond[] 1
  $srchconds[0] = New-Object autodesk.Connectivity.WebServices.SrchCond
  $srchconds[0].PropDefId = 0
  $srchconds[0].SrchOper = 1
  $srchconds[0].SrchTxt = $mvparam
  $srchconds[0].PropTyp = "AllProperties"
  $srchconds[0].SrchRule = "Must"
  $bookmark = ''
  $status = New-Object autodesk.Connectivity.WebServices.SrchStatus
  $items = $vault.ItemService.FindItemRevisionsBySearchConditions($srchconds, $null, $true, [ref]$bookmark, [ref]$status)
  $results = @()
  foreach($item in $items)
  {
    $row = New-Object itemData
    $row.Item = $item.ItemNum
    $row.Revision = $item.RevNum
    $row.Title = $item.Title
    $results += $row
  }
  $dsWindow.FindName("ItemsFound").ItemsSource = $results
}

function SelectItem
{
  $selectedItem = $dsWindow.FindName("ItemsFound").SelectedItem
  $Prop["Part Number"].Value = $selectedItem.Item
  $dsWindow.FindName("DataTab").IsSelected = $true
}

Similar to our last post about the item tab, we create a small C# class with few properties. The function SearchItems checks whether the arguments passed to the Button via the CommandParamenter are empty. In that case the function just returns and does nothing. Otherwise a generic search on the item master will be performed. How did I came across the settings for the search condition? I just started the vapiTrace and run a generic search in Vault. Then I read the function name and arguments from the vapiTrace.

The result of the search is then transformed into a list of our custom class and set as ItemsSource to the DataGrid.

As for our XAML, the DataGrid has a little context menu item with the “Select item” command. The bound function is the SelectItem, which sets the property Part Number to the selected number and then sets the first tab as active.

That’s it! Of course we can enhance this sample by showing more information for the items, or we can additionally filter the result and show just some data. We can also think or letting the user create new items right from within Inventor or AutoCAD. Then of course the XAML and code would be a bit longer. But overall, I think this sample shows a bit of XML and PowerShell technique, and with a few lines of code the result is quite impressive!

If you like to try this out, just download the ZIP package.

Posted in Data Standard, PowerShell, Vault API | 1 Comment

See items information of a file

itemToFile

Have you ever wished to access item and BOM information right from your file without the need to actually go to it? Here is a Data Standard sample that solves this problem. It’s a little tab that shows item information with the according item BOM of the current selected CAD file.

The technique is somewhat easy. It’s basically one XAML and one PS1 file. While the XAML is straight forward, it’s a grid with properties and a DataGrid for the BOM:

<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid x:Name="ItemData" VerticalAlignment="Top" Margin="10">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="80"/>
      <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition/>
      <RowDefinition/>
      <RowDefinition/>
      <RowDefinition/>
      <RowDefinition/>
      <RowDefinition/>
    </Grid.RowDefinitions>
    <Label Content="Item"/>
    <TextBox Text="{Binding Item}" Grid.Column="1"/>
    <Label Content="Revision" Grid.Row="1"/>
    <TextBox Text="{Binding Revision}" Grid.Column="1" Grid.Row="1"/>
    <Label Content="Title" Grid.Row="2"/>
    <TextBox Text="{Binding Title}" Grid.Column="1" Grid.Row="2"/>
    <Label Content="Category" Grid.Row="3"/>
    <TextBox Text="{Binding Category}" Grid.Column="1" Grid.Row="3"/>
    <Label Content="State" Grid.Row="4"/>
    <TextBox Text="{Binding State}" Grid.Column="1" Grid.Row="4"/>
  </Grid>
  <Grid Grid.Column="1" Margin="10">
    <DataGrid Name="bomList" AutoGenerateColumns="True" IsReadOnly="True" ColumnWidth="Auto" HorizontalGridLinesBrush="WhiteSmoke" VerticalGridLinesBrush="WhiteSmoke"/>
  </Grid>
</Grid>

The PS1 file is a bit more work. We basically have to collect the item information first and then transform the BOM information into a small list that fits into the DataGrid:

Add-Type @"
public class itemData
{
  public string Item {get;set;}
  public string Revision {get;set;}
  public string Title {get;set;}
  public string Category {get;set;}
  public string State {get;set;}
}
"@

function OnTabContextChanged_Item
{
  $xamlFile = [System.IO.Path]::GetFileName($VaultContext.UserControl.XamlFile)
  if ($VaultContext.SelectedObject.TypeId.SelectionContext -eq "FileMaster" -and $xamlFile -eq "Item.xaml")
  {
    $fileMasterId = $vaultContext.SelectedObject.Id
    $file = $vault.DocumentService.GetLatestFileByMasterId($fileMasterId)
    $items = $vault.ItemService.GetItemsByFileId($file.Id)
    $item = $items[0]
    SetItemData -itemId $item.id
    SetItemBomData -itemId $item.id
  }
}

function SetItemData($itemId)
{
  $properyDefinitions = $vault.PropertyService.GetPropertyDefinitionsByEntityClassId("ITEM")
  $properties = $vault.PropertyService.GetPropertiesByEntityIds("ITEM",$itemId)
  $props = @{}
  foreach ($property in $properties) {
    $propDef = $properyDefinitions | Where-Object { $_.Id -eq $property.PropDefId }
    $props[$propDef.DispName] = $property.Val
  }
  $item = New-Object itemData
  $item.Item = $props["Number"]
  $item.Revision = $props["Revision"]
  $item.Title = $props["Title (Item,CO)"]
  $item.State = $props["State"]
  $item.Category = $props["Category Name"]
  $dsWindow.FindName("ItemData").DataContext = $item
}

function SetItemBomData($itemId)
{
  $BOM = $vault.ItemService.GetItemBOMByItemIdAndDate($itemId, [DateTime]::MinValue, [Autodesk.Connectivity.WebServices.BOMTyp]::Tip, [Autodesk.Connectivity.WebServices.BOMViewEditOptions]::Defaults)
  $assocs = $BOM.ItemAssocArray | Where-Object { $_.ParItemId -eq $itemId }
  $childIds = $assocs | ForEach-Object { $_.CldItemId }
  $properyDefinitions = $vault.PropertyService.GetPropertyDefinitionsByEntityClassId("ITEM")
  $properties = $vault.PropertyService.GetPropertiesByEntityIds("ITEM",$childIds)
  $data = @()
  foreach ($id in $childIds) {
    $props = @{}
    $ppys = $properties | Where-Object { $_.EntityId -eq $id }
    foreach ($property in $ppys) {
      $propDef = $properyDefinitions | Where-Object { $_.Id -eq $property.PropDefId }
      $props[$propDef.DispName] = $property.Val
    }
    $item = New-Object itemData
    $item.Item = $props["Number"]
    $item.Revision = $props["Revision"]
    $item.Title = $props["Title (Item,CO)"]
    $item.State = $props["State"]
    $item.Category = $props["Category Name"]
    $data += $item
  }
  $dsWindow.FindName("bomList").ItemsSource = $data
  $dsDiag.Trace("<< SetItemBomData")
}

As you can see, in the XAML file we bind the TextBoxes to some properties, like Item, Revision, Title, etc. Usually you would bind such TextBoxes to a Prop[Item].Value or Prop[Revision].Value. Well, by doing so we would just get the values from the selected file, but we want the values from the item linked to the selected file. Now, we can either set the values one by one to the according TextBoxes, from the PowerShell script that runs behind, but in this case, I’d like to show you a more elegant way. We basically create in PowerShell our little C# class that we then set as a DataContext to the Grid that contains the TextBoxes. This way, whichever control is inside the Grid, like our TextBoxes, will be bound to the new source of data. So the binding now works against our little C# class. So in the PowerShell we simply populate the properties of the class with values, inject the class as DataContext to the Grid, and let the binding do the rest. In order to have this working, the attributes of the class must be properties (get;set;).

The DataGrid receives the information in a similar way, but via the ItemsSource. The nice thing about the DataGrind is that with the option AutoGenerateColumns the columns will be automatically generated – less work for us.

The only thing that must be done is to modify the OnTabContextChanged in the default.ps1 and add our function OnTabContextChanged_Item so that our code gets executed whenever a new file gets selected.

If you like to get this sample running on your side, just download the sample from GitHub and follow the instruction.

Enjoy!!

 

Posted in Data Standard, PowerShell, Vault API | 1 Comment

Menu item with Data Standard

blog-20141117

In preparation for my Autodesk University (Las Vegas) session with the topic “Introduction to Data Standard”, I’m creating samples around numbering, advanced dialogs in CAD and Vault, some cool tabs for Vault and also menu items. In the next weeks I will post the samples on this blog. However you are welcome to visit my session at AU and pass by to say hello!

Today, I’m going to talk about menu items. Data Standard offers an easy way to create additional menu items and place your personal custom logic behind. In order to demonstrate how this works, I will create a simple menu item that queues a job in the job queue. Actually, the item on the file context menu will place a PDF job in the job queue for the selected files. It’s pretty simple but it explains the technique behind and for all those of you who love powerJobs – our solution for creating PDF files and more – it’s a good and simple add-on.

In order to create a menu item, we need to do two things:

  • editing the mymenu.mnu
  • creating a little PowerShell script file

The mymenu.mnu is located in the DataStandard\Vault folder and contains all the menu item definitions. It’s a simple text file, so you can edit it with any convenient text editor. At the top of the file you will find text blocks or sections that all start with “item” and then the name of the section. An “item” represents a menu item. So, let’s create a new item for the PDF job queuing:

item newPDFJob
{
  Description = "Create PDF";
  Id = "cOCreatePDF";
  Hint = "Create PDF";
  Label = "Create PDF";
  MultiSelectEnabled = true;
  NavigationTypes = [File];
  ToolbarPaintStyle = TextAndGlyph;
  PSFile = "cOCreatePDF.ps1";
  Image="coolOrange.ico";
}

The most attributes of this section are probably self-explanatory. There are just a few things to take attention. The name of the item section must be unique and so must the Id attribute. Inside the mymenu.mnu file you will find a short description of the attributes at the top. The attribute, that we are interested in, is the PSFile, which points to a PowerShell script file. This file is located in the DataStandard\Vault\addinVault\Menus folders. Before we look to the PowerShell file, we have to define where our new menu item shall be displayed on the Vault UI. If you scroll down the mymenu.mnu, you will find further sections called “site” which describe the Vault toolbars and menu. As we like to add our menu item to the context of a file, the section we are looking for is called fileContext. It already exists, so just scroll down and look for it.

site fileContext
{
  Id="DSSiteFileContext";
  Label="myMenu";
  DeployAsPulldown=false;
  Location=FileContextMenu;
  MenuItems=[$newFile, $editFile,$NewJobPDF];
}

The attribute MenuItems contains the list of menu items that shall be displayed in the context menu. So, in our case the $NewJobPDF. Once you save the file and restart Vault, you should see your menu item like this:

menuItem

Let’s have a look to the cOCreatePDF.ps1 file. It does not exist yet, so let’s create one. And this is the content:

foreach ($selection in $vaultContext.CurrentSelectionSet)
{
  $jobParams = New-Object Autodesk.Connectivity.WebServices.JobParam[] 1
  $jobParams[0] = New-Object Autodesk.Connectivity.WebServices.JobParam
  $jobParams[0].Name = "FileId"
  $jobParams[0].Val = $selection.Id
  $text = "Create PDF for '"+$selection.Label+"'"
  $vault.JobService.AddJob("coolOrange.powerJobs.CreatePdfAsAttachment",$text,$jobParams,10)
}

The function iterates through the selected elements and for each element it adds a job into the job queue. For our job, we only pass the FileId as a parameter. So, the first couple of lines define the job parameter, while the last line adds the job to the queue with according arguments.

After next start of Vault, we will have a new menu item on the context of a file, which queues a powerJobs PDF creation for the selected files. Of course the logic of the menu item can be enhanced, so that the job gets queued only for certain file types or with some more parameters. However, that’s it. With just a few entries in the mymenu.mnu and an according PowerShell script, we have what we want.

I hope you have an idea how to create new menu items in Vault via Data Standard, an by the way, it’s worth having a look to the other menu items delivered with the standard, such as file and folder creation or edit and the like.

Posted in Data Standard, powerJobs, PowerShell, Vault API | Tagged , , , | Leave a comment

Combine Uses and Where Used

UsesWhereUsed

I’ve recently been asked how to create a tab in Vault that represents both, the use and where used of an assembly component. Immediately I thought this could be a good example for Data Standard. Basically, when you select an assembly, Vault shows you the “Use” and “Where used” as separate windows. But what if you like to expand the use, click a sub-component and see where this component is used? So, in this post I’m going to create a new tab that combines the 2 views, like this:

UsesWhereUsed

The solution for achieving this is pretty simple. We just need a tab with 2 tree-views and a bit of code for populating the tree-views. In order to keep the tab performing fast, we will collect the needed information on the go. In other words, we will collect the children only when the tree gets expanded, and we will collect the parents only when a component gets selected.

Now, a tree-view is a bit complex, as it behaves like a nested list. A list where every element has a sub-list, and each sub-element has a sub-sub-list, etc. In our particular case we want to populate the sub-elements only when really needed. So, creating an according object with PowerShell would be possible, but quite complex.

I prefer to keep the simple things in PowerShell and place the more complex things in C#, and then use that code in PowerShell.

So, I’ve created a little DLL which contains one class. That class exposes a Name (string), an Icon (image) and a Children (list) and Parents (list) property. While the Name and Icon are obvious, the Children and Parents properties collect the file associations. The getter of these properties will only be called as the user expands the tree or clicks on a component in order to see the where-used. So, the data will be required little by little. This is how the DLL looks like:

public class TreeNode
{
  Connection _con = null;
  File _file = null;
  WebServiceManager _svc { get { return _con.WebServiceManager; } }

  public string Name { get { return _file.Name; } }

  public List<TreeNode> Children {
    get {
      List<TreeNode> children = new List<TreeNode>();
      FileAssocArray[] fileAssociations = _svc.DocumentService.GetLatestFileAssociationsByMasterIds(new long[] { _file.MasterId }, FileAssociationTypeEnum.None, false, FileAssociationTypeEnum.Dependency, false, false, false,false);
      if (fileAssociations.First().FileAssocs != null)
        foreach (var fileAssociation in fileAssociations.First().FileAssocs)
          children.Add(new TreeNode(fileAssociation.CldFile, _con));    return children;
    }
  }

  public List<TreeNode> Parents
  {
    get {
      List<TreeNode> parents = new List<TreeNode>();
      FileAssocArray[] fileAssociations = _svc.DocumentService.GetLatestFileAssociationsByMasterIds(new long[] { _file.MasterId }, FileAssociationTypeEnum.Dependency, false, FileAssociationTypeEnum.None, false, false, false,false);
      if (fileAssociations.First().FileAssocs != null)
        foreach (var fileAssociation in fileAssociations.First().FileAssocs)
          parents.Add(new TreeNode(fileAssociation.ParFile, _con));
      return parents;
    }
  }

  public BitmapImage Icon
  {
    get {
      var props = _con.PropertyManager.GetPropertyDefinitions("FILE", null, PropertyDefinitionFilter.IncludeAll);
      var def = props["EntityIcon"];
      var fileIter = new FileIteration(_con,_file);
      ImageInfo prop = _con.PropertyManager.GetPropertyValue(fileIter, def, null) as ImageInfo;
      System.IO.MemoryStream ms = new System.IO.MemoryStream();
      prop.GetImage().Save(ms, System.Drawing.Imaging.ImageFormat.Png);
      prop.Dispose();
      System.Windows.Media.Imaging.BitmapImage bImg = new System.Windows.Media.Imaging.BitmapImage();
      bImg.BeginInit();
      bImg.StreamSource = ms;
      bImg.EndInit();
      return bImg;
    }
  }

  public TreeNode(File file, Connection con)
  {
    _file = file;
    _con = con;
  }
}

The most complex part is the extraction of the file icon. As you can see, the constructor of this class requires a file (Vault file object) and a Vault connection.

So, the PowerShell implementation is pretty short, as we only have to gather from Vault the currently selected file and pass this file to the DLL including the current Vault connection. As we get the first node (root node) from the DLL, we simply set the ItemsSource of our left TreeView (Uses) to our root node. The user can now expand the Uses TreeView and more and more data will be loaded. The following code is stored in a separate PS1 file called UsesWhereUsed.ps1 located in the Data Standard Vault\addinVault folder.

 
Add-Type -Path 'C:\ProgramData\Autodesk\Vault 2015\Extensions\DataStandard\Vault\addinVault\UsesWhereUsed.dll'

function OnTabContextChanged_UsesWhereUsed
{
  $xamlFile = [System.IO.Path]::GetFileName($VaultContext.UserControl.XamlFile)
  if ($VaultContext.SelectedObject.TypeId.SelectionContext -eq "FileMaster" -and $xamlFile -eq "Uses - Where used.xaml")
  {
    $file = $vault.DocumentService.GetLatestFileByMasterId($vaultContext.SelectedObject.Id)
    $treeNode = New-Object UsesWhereUsed.TreeNode($file, $vaultConnection)
    $dsWindow.FindName("Uses").ItemsSource = @($treeNode)
  }
}

As you can see, the PowerShell code loads the DLL from the according folder, so have the DLL in such folder, and then offer a function OnTabContextChanged_UsesWhereUsed. We will have to add this function in the OnTabContextChanged function of the default.ps1 file, like this:

function OnTabContextChanged
{
  OnTabContextChanged_UsesWhereUsed
  ...
  ....
  ..
}

At the beginning we spoke about the tab. So, the file UsesWhereUsed.XAML shall be located under Data Standard\Vault\Configuration\File. The first TreeView for the Uses looks pretty simple:

<TreeView x:Name="Uses" Background="{x:Null}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Icon}"/>
<Label Content="{Binding Name}" Grid.Column="1" />
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

In order to display correctly the Icon and the Name, we define a HierarchicalDataTemplate with a little Grid in it. The HierarchicalDataTemplate offers the ability to define where the child elements shall come from, so you see the additional ItemsSource set to Children.

The TreeView for the WhereUsed looks pretty much the same, except for the binding of the HierarchicalDataTemplate that obviously points to the Parents, and the ItemsSource of the TreeView itself, which points to the selected item of the Uses TreeView.

<TreeView x:Name="WhereUsed" ItemsSource="{Binding SelectedItem.Parents, ElementName=Uses, Mode=OneWay}" Background="{x:Null}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Parents}">

In other words, when you select an element in the Uses TreeView (left side), the WhereUsed TreeView gets notified and filled with the Parents of the selected item. So, the 2 TreeView talks to each other by themselves.

Here you can download the complete package including the source code for the C# DLL https://github.com/coolOrange-Public/UsesWhereUsedTab/archive/master.zip

I hope that with this example, you see how easily XAML, PowerShell and C# can work together to achieve cool things with relatively few code.

Posted in Data Standard, PowerShell, Vault API | Leave a comment