PowerShell XAML - Get textbox text into variable - wpf

I am writing an application in which I need to have a dialog box for user input. The problem I am having is getting the value from a textbox into a variable after the user clicks on the button.
[xml]$XAML_ConnectDialog = #"
<Window Name="Form_ConnectDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Connect" Height="176" Width="328" ResizeMode="NoResize" ShowInTaskbar="False">
<Grid>
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFB4B4B4" Offset="1"/>
<GradientStop Color="White" Offset="0.603"/>
</LinearGradientBrush>
</Grid.Background>
<TextBlock TextWrapping="Wrap" Text="Enter the hostname or IP address of the remote host to connect to." Margin="10,0,10,91"/>
<Label Content="Connect To:" HorizontalAlignment="Left" Height="27" VerticalAlignment="Top" Width="76" Margin="10,47,0,0"/>
<Button Name="Btn_ConnectDialog_Connect" Content="Connect" Height="20" Margin="194,88,26,20" IsDefault="True"/>
<TextBox Name="Txt_ConnectDialog_Input" HorizontalAlignment="Left" Height="23" Margin="91,51,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="208"/>
</Grid>
</Window>
"#
$XML_Node_Reader_ConnectDialog = (New-Object System.Xml.XmlNodeReader $XAML_ConnectDialog)
$ConnectDialog = [Windows.Markup.XamlReader]::Load($XML_Node_Reader_ConnectDialog)
$Btn_ConnectDialog_Connect = $ConnectDialog.FindName('Btn_ConnectDialog_Connect')
$Txt_ConnectDialog_Input = $ConnectDialog.FindName('Txt_ConnectDialog_Input')
$Btn_ConnectDialog_Connect.Add_Click({
$ConnectDialog.Hide()
$var = $Txt_ConnectDialog_Input.Text.ToString()
})
write-host $var
$ConnectDialog.ShowDialog() | Out-Null
Any help is appreciated.
Thanks

You're using Write-Host $var BEFORE you run the GUI. And since the GUI is used to define the variable in the first place, your Write-Host command will never return anything.
$var is not defined before your click-eventhandler. The eventhandler is a function, so the variable will be created in a local scope that only exists inside the function, and then deleted after the function/eventhandler is done. I've fixed this by specifying the eventhandler to store the value in the variable $var in the script scope, so it will be available until the script is finished.
Fixed script:
[xml]$XAML_ConnectDialog = #"
<Window Name="Form_ConnectDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Connect" Height="176" Width="328" ResizeMode="NoResize" ShowInTaskbar="False">
<Grid>
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFB4B4B4" Offset="1"/>
<GradientStop Color="White" Offset="0.603"/>
</LinearGradientBrush>
</Grid.Background>
<TextBlock TextWrapping="Wrap" Text="Enter the hostname or IP address of the remote host to connect to." Margin="10,0,10,91"/>
<Label Content="Connect To:" HorizontalAlignment="Left" Height="27" VerticalAlignment="Top" Width="76" Margin="10,47,0,0"/>
<Button Name="Btn_ConnectDialog_Connect" Content="Connect" Height="20" Margin="194,88,26,20" IsDefault="True"/>
<TextBox Name="Txt_ConnectDialog_Input" HorizontalAlignment="Left" Height="23" Margin="91,51,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="208"/>
</Grid>
</Window>
"#
$XML_Node_Reader_ConnectDialog = (New-Object System.Xml.XmlNodeReader $XAML_ConnectDialog)
$ConnectDialog = [Windows.Markup.XamlReader]::Load($XML_Node_Reader_ConnectDialog)
$Btn_ConnectDialog_Connect = $ConnectDialog.FindName('Btn_ConnectDialog_Connect')
$Txt_ConnectDialog_Input = $ConnectDialog.FindName('Txt_ConnectDialog_Input')
$Btn_ConnectDialog_Connect.Add_Click({
$ConnectDialog.Hide()
$script:var = $Txt_ConnectDialog_Input.Text.ToString()
})
$ConnectDialog.ShowDialog() | Out-Null
write-host $var

Related

Feed XML into XAML/PowerShell WPF Form

I had a question along a similar topic last week which ultimatly is the same issue but in that scenario I managed to get round this with a PowerShell array on static data thanks to someone on the forum suggesting.
This time round I cant use static so I am somewhat back to my root problem.
I have created a WPF XAML form in Visual Studio and am taking this back to Powershell as my remit with the customer is 'low-code'. The item in question is loading an xml file into the form to populate a list box. Reason for a list box is cleanliness of changing the colour of the background.
Now in VS this works find with a Data Provider but for reasons I cannot find an answer to, this just simply will not work when taken back to PowerShell so I have looked for alternate way.
So I have a simple XML as below:
<?xml version="1.0"?>
<Configuration>
<AllowedAutoStart>Application 1</AllowedAutoStart>
<DenyRemoveAutoStart>Application 2</DenyRemoveAutoStart>
</Configuration>
I want to feed this into my PowerShell/XAML Hybrid Script and simply bind the contents to the appropriate list box (below code is just starting with allowed apps)
I have tried a few different ideas from across the forum before posting but none quite get there. Below is the code I have at present, it doesnt work but doesnt produce any errors either :-)
Appreciate any guidance.
# Load Assembly
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationCore
Add-Type -AssemblyName WindowsBase
#Declare XAML Code
[xml]$AppGeneratorWindow = #"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="App Config Generator" Height="350" Width="600" WindowStartupLocation="CenterScreen" Top="5" ResizeMode="NoResize">
<Window.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFAA3D3D" Offset="1"/>
</LinearGradientBrush>
</Window.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="115*"/>
<ColumnDefinition Width="132*"/>
<ColumnDefinition Width="543*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="381*"/>
<RowDefinition Height="241*"/>
</Grid.RowDefinitions>
<Label Name="AllProgramsLabel" Content="All Programs" HorizontalAlignment="Left" Margin="28.333,20,0,0" VerticalAlignment="Top" Foreground="#FFFEFBFB" FontSize="14" FontWeight="Bold" RenderTransformOrigin="2.696,-3.142" Grid.Column="1" Grid.ColumnSpan="2"/>
<Button Name="AddButton" Content="Add >>" HorizontalAlignment="Left" Margin="34,83,0,0" VerticalAlignment="Top" Width="166" FontWeight="Bold" FontSize="14" Height="28" BorderBrush="#FF070606" Background="#FF933838" Foreground="#FFFCFAFA" Grid.Column="3" RenderTransformOrigin="0.416,-0.906"/>
<Label Name="WindowsStartupLabel" Content="Windows Startup" HorizontalAlignment="Left" Margin="236,20,0,0" VerticalAlignment="Top" Foreground="#FFFEFBFB" FontSize="14" FontWeight="Bold" RenderTransformOrigin="2.696,-3.142" Grid.Column="3"/>
<Button Name="RemoveButton" Content="<< Remove" HorizontalAlignment="Left" Margin="34,169,0,0" VerticalAlignment="Top" Width="166" FontWeight="Bold" FontSize="14" Height="28" BorderBrush="#FF070606" Background="#FF933838" Foreground="#FFFCFAFA" Grid.Column="3" Grid.RowSpan="2" RenderTransformOrigin="0.51,-0.503"/>
<ListBox Name="AllProgramsListBox" Grid.ColumnSpan="2" Grid.Column="1" HorizontalAlignment="Left" Height="132" Margin="28,65,0,0" Background="#FFAA3D3D" VerticalAlignment="Top" Width="123" Grid.RowSpan="2"/>
<ListBox Name="StartupListBox" Grid.Column="3" HorizontalAlignment="Left" Height="132" Margin="237,65,0,0" Background="#FFAA3D3D" VerticalAlignment="Top" Width="123" Grid.RowSpan="2"/>
</Grid>
</Window>
"#
#List Boxes
$AllProgramsListBox = $window.FindName("AllProgramsListBox")
$ConfigurationFile = "$env:ProgramData\WindowsStartupTool\AutoStartConfig.XML"
[xml]$ConfigFile = Get-Content $ConfigurationFile
foreach ($entry in $ConfigFile.Configuration.AllowedAutoStart.add)
{
write-host $entry
$AllProgramsListBox.Items.Add($($entry))
}
#Declare & Create the form
$reader=(New-Object System.Xml.XmlNodeReader $AppGeneratorWindow)
$window = [Windows.Markup.XamlReader]::Load($reader)
##########################################
#Launch the User Interface #
[void]$window.ShowDialog() #
##########################################
This is launched from PowerShell which is where I have to get it to work from in some capacity.
Thanks in advance
You're very close. All you really have to do is move the part where you read the config file and do the foreach ($entry.. to below the creation of the window.
As the code is now, you're trying to use variable $window where it is not yet defined.
Directly below the XAML code put:
#Declare & Create the form
$reader = New-Object System.Xml.XmlNodeReader $AppGeneratorWindow
$window = [Windows.Markup.XamlReader]::Load($reader)
#List Boxes
$AllProgramsListBox = $window.FindName("AllProgramsListBox")
$ConfigurationFile = "$env:ProgramData\WindowsStartupTool\AutoStartConfig.XML"
[xml]$ConfigFile = Get-Content $ConfigurationFile -Raw
foreach ($entry in $ConfigFile.Configuration.AllowedAutoStart) {
Write-Host $entry
$AllProgramsListBox.Items.Add($entry)
}
##########################################
#Launch the User Interface #
[void]$window.ShowDialog() #
##########################################

How to apply "Uniform" stretch property to a composite path with gradients in WPF/XAML?

Folks
I am trying to draw my company's logo vectorially with XAML, in order to put it inside UI containers whenever it is convenient.
The only requisite is that the logo won't be clipped or deformed, so the "Uniform" stretch property is what I am looking for.
Sample "semi-working" code is below:
<Grid Width="160" Height="153" >
<Rectangle Clip="M 80,0 c 41.793,0 75.879,34.086 75.879,75.878 0,0.75 -0.015,1.496 -0.036,2.24 l -33.846,-57.969 -42.204,80.387 -39.421,-68.175 -35.758,34.917 c 4.294,-37.769 36.501,-67.278 75.386,-67.278 z" Margin="0">
<Rectangle.Fill>
<RadialGradientBrush GradientOrigin="44,14" Center="44,44" RadiusX="125" RadiusY="125" MappingMode="Absolute">
<GradientStop Color="#FF1C545C" Offset="0.63"/>
<GradientStop Color="#FF3BB3C3" Offset="0.23"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Clip="M 151,102 c -10.528,29.287 -38.601,50.33 -71.436,50.33 -36.935,0 -67.845,-26.625 -74.533,-61.662 l 32.586,-31.299 42.204,75.131 44.986,-84.096 26.193,51.596 z">
<Rectangle.Fill>
<RadialGradientBrush RadiusY="100" RadiusX="100" GradientOrigin="49,87" Center="49,87" MappingMode="Absolute">
<GradientStop Color="{DynamicResource MarinhoMiotec}" Offset="0.27"/>
<GradientStop Color="#FF003052" Offset="0.63"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
The problem is: when I put this grid inside another icon-sized grid, the drawing does not shrink to uniformly fit inside it.
I guess it is so because the grid where the rectangles are drawn has fixed heigth and width. I already tried to create a single discontinuous path, but then I could not put different colors on each half of the logo.
Should I chose a different container, or should I make the coordinates relative, or use a transform, or create a style, or make a brush... I am confused with so many possible lines of action...
Any help would be appreciated.
Thanks for reading
Try wrapping your logo inside a ViewBox: http://msdn.microsoft.com/en-us/library/system.windows.controls.viewbox.aspx
Here is an example:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="150" />
</Grid.RowDefinitions>
<Viewbox>
<Grid Width="160" Height="153" >
<Rectangle Clip="M 80,0 c 41.793,0 75.879,34.086 75.879,75.878 0,0.75 -0.015,1.496 -0.036,2.24 l -33.846,-57.969 -42.204,80.387 -39.421,-68.175 -35.758,34.917 c 4.294,-37.769 36.501,-67.278 75.386,-67.278 z" Margin="0">
<Rectangle.Fill>
<RadialGradientBrush GradientOrigin="44,14" Center="44,44" RadiusX="125" RadiusY="125" MappingMode="Absolute">
<GradientStop Color="#FF1C545C" Offset="0.63"/>
<GradientStop Color="#FF3BB3C3" Offset="0.23"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Clip="M 151,102 c -10.528,29.287 -38.601,50.33 -71.436,50.33 -36.935,0 -67.845,-26.625 -74.533,-61.662 l 32.586,-31.299 42.204,75.131 44.986,-84.096 26.193,51.596 z">
<Rectangle.Fill>
<RadialGradientBrush RadiusY="100" RadiusX="100" GradientOrigin="49,87" Center="49,87" MappingMode="Absolute">
<GradientStop Color="{DynamicResource MarinhoMiotec}" Offset="0.27"/>
<GradientStop Color="#FF003052" Offset="0.63"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Viewbox>
</Grid>
This will render the logo in a 50x50 grid cell.

Strange behavior on ShowDialog in WPF

I create separate Window, design it with XAML and when I invoke ShowDialog from main form it seems like my dialog (Window) blinks once and then shows itself. Is it a common behavior? I didn't notice that in while working with Windows Forms. I also ran application on another computer, and get the same thing. It bothers me, cause I was developing a simple game, and it's not the effect I would like users to experience.
It is not a complicated dialog, considering the design. It contains just label and button. Here is one sample:
<Window x:Class="A_Boggle.Info"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Info" Height="300" Width="670" AllowsTransparency="True" WindowStyle="None" Background="Transparent" BorderBrush="Transparent" Foreground="Transparent" ShowInTaskbar="False" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Closing="Window_Closing">
<Grid>
<Border Background="Transparent" Visibility="{Binding Visibility}">
<Border BorderBrush="#FF7C4400" BorderThickness="4"
CornerRadius="10,0,10,0" VerticalAlignment="Center" HorizontalAlignment="Center" Height="177.5" Width="596.25">
<Border.Background>
<RadialGradientBrush Center="0.5,0.5" GradientOrigin="0.5,0.5" RadiusX="0.479" RadiusY="0.524">
<GradientStop Color="#FFF58611" Offset="0"/>
<GradientStop Color="#FFF58611" Offset="0.11798000335693359"/>
<GradientStop Color="#FFE9B231" Offset="1"/>
</RadialGradientBrush>
</Border.Background>
<Border.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Opacity="0.5" Direction="270" ShadowDepth="0.7" />
</Border.BitmapEffect>
<Grid>
<Separator Height="20" Name="separator1" Margin="8.75,0,6.25,45" VerticalAlignment="Bottom" />
<Button Style="{DynamicResource OrangeButton}" Margin="406.25,0,6.25,6" Height="37.75" VerticalAlignment="Bottom" FontSize="16" Name="dialogButton" Click="dialogButton_Click"></Button>
<Label FontFamily="Resources/#French Grotesque" FontSize="20" Foreground="#FF7C4400" Margin="8.75,20,6.25,71.25" Name="messageLabel"></Label>
</Grid>
</Border>
</Border>
</Grid>
No. Blinking on ShowDialog is not a common behaviour. Could you first try with an empty Window:
new Window().ShowDialog();
in order to see if the problem persists?
Aside from the main topic, WPF/XAML might be not the proper technology for a complicated game due to performance reasons (although for a simple one must be OK).

WPF : How to assign click event to the form

How to assign Click event in this? I want to do something when mouse click on this window.
It's doesn't have Click properties in both Window and Canvas
<Window Loaded="Window_Loaded"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="InClassApp.UI.TextNotify"
x:Name="Window"
Title="TextNotify"
Width="400" Height="100"
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent"
ShowInTaskbar="False">
<Border CornerRadius="5">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBAFDFF" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<Canvas x:Name="LayoutRoot" >
.......
</Canvas>
</Border>
You could handle the MouseLeftButtonUp event instead.
you might want to add MouseLeftButtonDown="Window_MouseLeftButtonDown" on your <Window> element.
and add following in the code-behind file.
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// do some stuff here.
}

How to position UserControl in the parent canvas

I want to place this UserControl at Canvas.Left="168", Canvas.Top="213".
However, the control appears at a corner. What should I do?
If I put the values at the point of usage for this class, the values are returned as NaN
In that case how can I get the correct Left and Top Values?
Usage:
<Canvas x:Name="DesignerCanvas"
ClipToBounds="True"
SnapsToDevicePixels="True">
<Gr:BareNode />
</Canvas>
UserControl:
<UserControl x:Class="DiagramDesigner.BareNode"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ContentControl Width="50"
Height="50"
Padding="2"
Canvas.Left="168" Canvas.Top="213">
<Ellipse IsHitTestVisible="False" >
<Shape.Fill>
<RadialGradientBrush Center="0.2, 0.2" GradientOrigin="0.2, 0.2" RadiusX="0.8" RadiusY="0.8">
<GradientStop Color="LightBlue" Offset="0"/>
<GradientStop Color="Blue" Offset="0.9"/>
</RadialGradientBrush>
</Shape.Fill>
</Ellipse>
</ContentControl>
</Grid>
</UserControl>
I'm not sure if you tried this or not, but just from looking at the XAML it appears that you are trying to set the position of the user control inside the user control. That won't work. You need to put it where you use the user control
<Canvas x:Name="DesignerCanvas"
ClipToBounds="True"
SnapsToDevicePixels="True">
<Gr:BareNode Canvas.Left="168" Canvas.Top="213"/>
</Canvas>
Take the Canvas.Left="168" Canvas.Top="213" part out of the ContentControl declaration of inside the user control.

Resources