I need some help with Powershell and WPF.
I am modifying an Add-In that someone made using WPF and powershell. So I'm not 100% sure how the xaml structure is laid out. What I want to do is to modify the Text property of a certain element that is generated during runtime. I used Snoop2.8.0 and found the element that I want to modify, and it has a Name property "FreeTextBox". I intend to use the FindName method to get to the element, however, the FindName method returns nothing.
I have read in a few posts that there is a separate thing called contentPresenter where these runtime elements are stored and that I need to reference it to get to my textbox, however, I don't know how to do this. I would appreciate if anyone could point me in the right direction.
Regards Ilyas
Edit: Code for the form
<?xml version="1.0" encoding="utf-8"?>
<WPF:DSWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WPF="clr-namespace:dataStandard.UI.View;assembly=dataStandard.UI" xmlns:system="clr-namespace:System;assembly=mscorlib" x:Name="InventorWindow" WindowStyle="ToolWindow" ShowInTaskbar="False" Topmost="True" SizeToContent="WidthAndHeight" Background="#F0F0F0" ResizeMode="NoResize">
<WPF:DSWindow.Resources>
<Style x:Key="DynamicDataGridCellStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ComboBox ItemsSource="{Binding ListValues}" Text="{WPF:ValidatedBinding Value}" IsEditable="True"></ComboBox>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}" />
</Trigger>
<DataTrigger Binding="{Binding ListValues.Count}" Value="0">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBox Text="{WPF:ValidatedBinding Value}"></TextBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Typ}" Value="DateTime">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<DatePicker SelectedDate="{WPF:ValidatedBinding Value, StringFormat='dd/MM/yyyy'}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Typ}" Value="Boolean">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ComboBox SelectedItem="{WPF:ValidatedBinding Value}">
<system:Boolean>True</system:Boolean>
<system:Boolean>False</system:Boolean>
</ComboBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsReadOnly}" Value="True">
<Setter Property="Background" Value="#F0F0F0"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type DatePicker}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="FileNameStyle" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding CreateMode}" Value="True"></Condition>
<Condition Binding="{Binding ElementName=NumSchms, Path=IsEnabled}" Value="True"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="Text" Value="{Binding UIString[LBL59]}"></Setter>
<Setter Property="IsReadOnly" Value="True"></Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding CreateMode}" Value="True"></Condition>
<Condition Binding="{Binding ElementName=NumSchms, Path=IsEnabled}" Value="False"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="Text" Value="{Binding Prop[DocNumber].Value}"></Setter>
</MultiDataTrigger>
<DataTrigger Binding="{Binding EditMode}" Value="True">
<Setter Property="Background" Value="#F0F0F0" />
<Setter Property="IsReadOnly" Value="True"></Setter>
<Setter Property="Text" Value="{Binding Prop[_FileName].Value}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="NumSchmStyle" TargetType="{x:Type ComboBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding CreateMode}" Value="True">
<Setter Property="ItemsSource" Value="{Binding PsList[GetNumSchms]}"></Setter>
<Setter Property="IsEnabled" Value="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding EditMode}" Value="True">
<Setter Property="Text" Value="{Binding UIString[LBL27]}"></Setter>
<Setter Property="Background" Value="#F0F0F0" />
<Setter Property="IsEditable" Value="True"></Setter>
<Setter Property="IsReadOnly" Value="True"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Content}" Value="{x:Null}">
<Setter Property="BorderThickness" Value="1"></Setter>
<Setter Property="BorderBrush" Value="#ff0000"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<XmlDataProvider x:Key="ComboDataSource" Source="C:\CHM Vault\Libraries\data.xml"></XmlDataProvider>
<XmlDataProvider x:Key="JobCodeDataSource" Source="C:\CHM Vault\Libraries\jobcode.xml"></XmlDataProvider>
</WPF:DSWindow.Resources>
<Window.Style>
<Style TargetType="{x:Type WPF:DSWindow}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding CreateMode}" Value="True"></Condition>
<Condition Binding="{Binding CopyMode}" Value="True"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="Title">
<Setter.Value>
<MultiBinding StringFormat="{}{0} - '{1}'">
<Binding Path="UIString[LBL60]" />
<Binding Path="PathAndFileNameHandler.OriginalFileName" />
</MultiBinding>
</Setter.Value>
</Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding CreateMode}" Value="True"></Condition>
<Condition Binding="{Binding CopyMode}" Value="False"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="Title">
<Setter.Value>
<MultiBinding StringFormat="{}{0} - '{1}'">
<Binding Path="UIString[LBL24]" />
<Binding Path="PathAndFileNameHandler.OriginalFileName" />
</MultiBinding>
</Setter.Value>
</Setter>
</MultiDataTrigger>
<DataTrigger Binding="{Binding CreateMode}" Value="False">
<Setter Property="Title">
<Setter.Value>
<MultiBinding StringFormat="{}{0} - '{1}'">
<Binding Path="UIString[LBL25]" />
<Binding Path="PathAndFileNameHandler.FileName" />
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Style>
<DockPanel HorizontalAlignment="Left" Height="Auto" Margin="20" VerticalAlignment="Top" Width="Auto">
<Grid Margin="0,10,0,0" DockPanel.Dock="Bottom" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="White" BorderThickness="5" VerticalAlignment="Bottom" HorizontalAlignment="Center" Visibility="{Binding CopyMode, Converter={StaticResource BooleanToVisibilityConverter}}" Margin="5,0,5,22">
<Image VerticalAlignment="Center" Width="120" Height="120" Source="{Binding Prop[Thumbnail].Value}" />
</Border>
<Button Command="{Binding CloseWindowCommand, ElementName=InventorWindow}" IsEnabled="True" Grid.Column="2" Margin="0,5,0,5" Width="80" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding UIString[LBL35], FallbackValue=Cancel}" Content="{Binding UIString[BTN1], FallbackValue=OK}" />
<Button Grid.Column="4" Width="80" HorizontalAlignment="Right" Margin="0,5,0,5" VerticalAlignment="Center" Command="{Binding CancelWindowCommand, ElementName=InventorWindow}" IsCancel="true" Content="{Binding UIString[BTN2], FallbackValue=Cancel}" />
</Grid>
<Grid Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" DockPanel.Dock="Left">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid Name="GeneralFileProp" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140" />
<ColumnDefinition Width="350" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{Binding UIString[LBL10], FallbackValue=Number Scheme}" />
<ComboBox Grid.Column="1" Grid.Row="0" x:Name="NumSchms" DisplayMemberPath="Name" SelectedIndex="0" Style="{StaticResource NumSchmStyle}" />
<Label Grid.Row="2" Grid.Column="0" Content="{Binding UIString[LBL31], FallbackValue=Number}" />
<WPF:DSNumSchemeCtrl Grid.Row="2" Grid.Column="1" Scheme="{Binding SelectedItem, ElementName=NumSchms}" IsEnabled="{Binding IsEnabled, ElementName=NumSchms}" GeneratedNumberProperty="DocNumber" />
<Label Content="Folder" Grid.Row="4" Grid.Column="0" Visibility="{Binding CreateMode, Converter={StaticResource BooleanToVisibilityConverter}}" />
<WrapPanel Name="BreadCrumb" Grid.Column="1" Grid.Row="4" ItemWidth="165">
<WrapPanel.Resources>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Margin" Value="0,5,15,0" />
<Setter Property="ToolTip" Value="{Binding Path=SelectedValue.Name, RelativeSource={RelativeSource Self}}" />
</Style>
</WrapPanel.Resources>
</WrapPanel>
<Label Content="Description" Grid.Column="0" Grid.Row="6" />
<TextBox Text="{Binding Prop[Description].Value}" Grid.Column="1" Grid.Row="6" x:Name="Description" VerticalScrollBarVisibility="Auto" Height="50" TextWrapping="Wrap" AcceptsReturn="True" />
<Label Content="Path" Grid.Column="0" Grid.Row="8" />
<TextBox Text="{Binding PathAndFileNameHandler.Path}" Grid.Column="1" Grid.Row="8" IsReadOnly="True" Background="#F0F0F0" />
<Label Content="File Name" Grid.Row="10" Grid.Column="0" />
<TextBox Grid.Row="10" Grid.Column="1" x:Name="FILENAME" Style="{StaticResource FileNameStyle}" />
</Grid>
<Grid Name="ModelProp" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140" />
<ColumnDefinition Width="350" />
</Grid.ColumnDefinitions>
<Label Content="Category" Grid.Row="0" Grid.Column="0" />
<ComboBox x:Name="ItemCategory" Grid.Row="0" Grid.Column="1" ItemsSource="{Binding Source={StaticResource ComboDataSource}, XPath=/Data/ItemCat/*}" DisplayMemberPath="@Name" SelectedValue="{Binding Prop[Item Category].Value}" SelectedValuePath="@Name" IsEnabled="{Binding CreateMode}" />
<!-- <ComboBox x:Name="Categories" DisplayMemberPath="Name" SelectedItem="{Binding DynamicPropertiesCategory}" ItemsSource="{Binding PsList[GetCategories]}" SelectedIndex="0" Grid.Row="0" Grid.Column="1" IsEnabled="{Binding CreateMode}" /> -->
<Label Content="Model" Grid.Row="2" Grid.Column="0" />
<ComboBox x:Name="Model" Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Source={StaticResource ComboDataSource}, XPath=/Data/ModelStd/*}" DisplayMemberPath="@Name" Text="{Binding Prop[Model].Value}" SelectedValue="{Binding Prop[Model].Value}" SelectedValuePath="@Name" IsEditable="True" />
<Label Content="Order Code" Grid.Row="4" Grid.Column="0" />
<TextBox Text="{Binding Prop[Order Code].Value}" Grid.Row="4" Grid.Column="1" />
<Label Content="Rating" Grid.Row="6" Grid.Column="0" />
<TextBox Text="{Binding Prop[Rating].Value}" Grid.Row="6" Grid.Column="1" />
<Label Content="Brand" Grid.Row="8" Grid.Column="0" />
<TextBox Text="{Binding Prop[Brand].Value}" Grid.Row="8" Grid.Column="1" />
<Label Content="Manufacturing Length" Grid.Row="10" Grid.Column="0" />
<TextBox Text="{Binding Prop[Manufacturing Length].Value}" Grid.Row="10" Grid.Column="1" />
</Grid>
<Grid Name="DrawingProp" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
<RowDefinition Height="8" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140" />
<ColumnDefinition Width="350" />
</Grid.ColumnDefinitions>
<Label Content="Job Code" Grid.Row="0" Grid.Column="0" />
<ComboBox x:Name="JobCode" Grid.Column="1" Grid.Row="0" ItemsSource="{Binding Source={StaticResource JobCodeDataSource}, XPath=/JobCode/*}" DisplayMemberPath="@Code" SelectedValue="{Binding Prop[Job Code].Value}" SelectedValuePath="@Code" IsEnabled="True"/>
<Label Content="Client" Grid.Row="2" Grid.Column="0" />
<TextBox Name="Client" Text="{Binding Prop[Client].Value}" Grid.Row="2" Grid.Column="1" IsEnabled="False" />
<Label Content="Project Title" Grid.Row="4" Grid.Column="0" />
<TextBox Name="ProjectTitle" Text="{Binding Prop[Project Title].Value}" Grid.Row="4" Grid.Column="1" IsEnabled="False"/>
<TextBox Name="Treatment" Text="{Binding Prop[Treatment].Value}" Grid.Row="6" Grid.Column="1" IsEnabled="True"/>
</Grid>
</Grid>
</DockPanel>
</WPF:DSWindow>
Code for the behavior
function InitializeWindow
{
$dsWindow.Width = 500
$dsWindow.Height = 400
$Prop["Job Code"].add_PropertyChanged({p
param( $parameter)
StateChanged
})
If (($Prop["_FileExt"].Value -eq "IDW") -or ($Prop["_FileExt"].Value -eq "DWG"))
{
$dsWindow.FindName("ModelProp").Visibility="Collapsed"
$dsWindow.FindName("DrawingProp").Visibility="Visible"
}
Else
{
$dsWindow.FindName("ModelProp").Visibility="Visible"
$dsWindow.FindName("DrawingProp").Visibility="Collapsed"
}
$mWindowName = $dsWindow.Name
switch($mWindowName)
{
"InventorWindow"
{
#rules applying for Inventor
}
"AutoCADWindow"
{
#rules applying for AutoCAD
}
default
{
#rules applying commonly
}
}
if ($Prop["_CreateMode"].Value)
{
$mappedRootPath = $Prop["_VaultVirtualPath"].Value + $Prop["_WorkspacePath"].Value
$mappedRootPath = $mappedRootPath -replace "\\", "/" -replace "//", "/"
if ($mappedRootPath -eq '')
{
$mappedRootPath = '$'
}
$rootFolder = $vault.DocumentService.GetFolderByPath($mappedRootPath)
$root = New-Object PSObject -Property @{ Name = $rootFolder.Name; ID=$rootFolder.Id }
AddCombo -data $root
}
}
function AddinLoaded
{
#Executed when DataStandard is loaded in Inventor
}
function AddinUnloaded
{
#Executed when DataStandard is unloaded in Inventor
}
function GetNumSchms
{
try
{
$numSchems = $vault.DocumentService.GetNumberingSchemesByType('Activated')
if ($numSchems.Count -gt 0)
{
$list = New-Object 'System.Collections.Generic.List[System.Object]'
foreach ($item in $numSchems)
{
if ($item.IsDflt)
{
$list.Insert(0,$item)
}
else
{
$list.Add($item)
}
}
return $list
}
}
catch [System.Exception]
{
#[System.Windows.MessageBox]::Show($error)
}
}
function GetCategories
{
if ($Prop["_CreateMode"].Value)
{
$cats = $vault.CategoryService.GetCategoriesByEntityClassId("FILE", $true)
if ($cats.Count -gt 0)
{
$list = New-Object 'System.Collections.Generic.List[System.Object]'
foreach ($item in $cats)
{
$list.Add($item)
}
return $list
}
}
if ($Prop["_EditMode"].Value)
{
return GetCategoryByFileName $Prop["_FileName"].Value
}
}
function OnPostCloseDialog
{
$mWindowName = $dsWindow.Name
switch($mWindowName)
{
"InventorWindow"
{
#rules applying for Inventor
If (($Prop["_FileExt"].Value -eq "IDW") -or ($Prop["_FileExt"].Value -eq "DWG"))
{
If ($Prop["DocNumber"].Value.substring(0,1) -eq "Q")
{
$Prop["DocNumber"].Value=$Prop["DocNumber"].Value.substring($Prop["DocNumber"].Value.length-5,5)
}
}
}
"AutoCADWindow"
{
#rules applying for AutoCAD
}
default
{
#rules applying commonly
}
}
}
function GetCategoryByFileName($fileName)
{
$filePropDefs = $vault.PropertyService.GetPropertyDefinitionsByEntityClassId("FILE");
$fileNamePropDef = $filePropDefs | Where-Object {$_.SysName -eq "ClientFileName"}
$searchCond = New-Object -type Autodesk.Connectivity.WebServices.SrchCond
$searchCond.PropDefId = $fileNamePropDef.Id
$searchCond.PropTyp = [Autodesk.Connectivity.WebServices.PropertySearchType]::SingleProperty
$searchCond.SrchTxt = $fileName
$searchCond.SrchOper = 3
$searchCond.SrchRule = [Autodesk.Connectivity.WebServices.SearchRuleType]::Must
$bookmark = ""
$status = $null
$cat = $null
$findFilesBySearchConditions = $vault.DocumentService.FindFilesBySearchConditions($searchCond, $null, $null, $false, $true, [ref]$bookmark, [ref]$status)
if ($findFilesBySearchConditions -ne $null)
{
$cat = New-Object Autodesk.Connectivity.WebServices.Cat
$cat.Id = $findFilesBySearchConditions[0].Cat.CatId
$cat.Name = $findFilesBySearchConditions[0].Cat.CatName
}
return $cat;
}
function StateChanged
{
$jobdata="C:\ProgramData\Autodesk\Vault 2016\Extensions\DataStandard\CAD\Configuration\jobcode.xml"
$jobcodes = [xml](Get-Content $jobdata)
$job=$jobcodes.JobCode.Job|where {$_.Code -eq $Prop["Job Code"].Value}
$Prop["Project Title"].Value=$job.Title
$Prop["Client"].Value=$job.Client
#[System.Windows.Forms.MessageBox]::Show($dswindow.FindName("FreeTextBox").Text)
#$dsWindow.FindName("FreeTextBox").Text=$Prop["Job Code"].Value
}
As can be seen in the last line of this second code, I am trying to get use findname to get the FreeTextBox that was created from the main application. Unfortunately I don't have the code that creates the textbox as this is an addin that calls from the main application. I used snoop to find out the properties of the element itself, but stack doesn't allow me to post images yet.
The FreeTextBox is probably in another usercontrol, or datatemplate loaded to your window and therefore is in different NameScope. FindName looks for elements only in current namescope.
you need to recursively traverse entire visual subtree of the window using VisualTreeHelper API and check name property of each element in order to find the FreeTextBox. Just use GetChildrenCount
and GetChild
methods.