2

I am working on a PowerShell (Core, 7) module that shall have a WPF GUI. I want to organize the code in a better way, splitting up the XAML, e.g. Styles.xaml, Colors.xaml and Templates.xaml.

The code consists of multiple ps1 files which are assembled into one psm1 module file during compilation. Aside the module file I put the psd1 as well as the UI directory, containing all xaml files:

\_ HIWE (the module)
 |_ HIWE.psm1
 |_ HIWE.psd1
 \_ UI
  |_ App.xaml
  |_ Colors.xaml 
  |_ Styles.xaml
  \_ Templates.xaml

The App.xaml references to the same directory as App.xaml:

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Colors.xaml"/>
            <ResourceDictionary Source="Styles.xaml"/>
            <ResourceDictionary Source="Templates.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Issue

So, as an installed module, depending on installed as CurrentUser or AllUsers scope, this would end up in different pathes.

It seems that the [System.Windows.Markup.XamlReader]::Load($appXmlReader) is not using the reference relatively from the location of the App.xaml but from the cwd of the execution. This would make it necessary to put in the directory in an absolute way which is not possible due to the different locations where it might be installed to.

It is not the issue to reference to UI\filename.xaml instead, this is what I already tested.

Question

How do you solve this issue when you want to split up your WPF / XAML code effectively and don't want to end up in a huuuuuge file?

1
  • 2
    If it is really the process' current directory that relative paths refer to, you can try [Environment]::CurrentDirectory = "$PSScriptRoot\UI" in your module, before calling [System.Windows.Markup.XamlReader]::Load($appXmlReader) However, it seems that paths (URIs) to resource files are assumed to refer to "files compiled into either an executable or library WPF assembly."; similarly, the use of Pack URIs is tied to .NET assemblies. Commented Mar 29 at 18:02

1 Answer 1

3

As mklement0 commented, XAML resources are normally tied to .NET assemblies. When using "loose" XAML files, a workaround is to load and merge them manually from the PowerShell script.

Example:

Add-Type -AssemblyName PresentationFramework

# Imports a XAML file relative to the current script's directory.
Function Import-Xaml {
    param (
        [Parameter(Mandatory)] [string] $RelativePath
    )
    $fullPath = Join-Path $PSScriptRoot $RelativePath
    [Windows.Markup.XamlReader]::Parse((Get-Content -Path $fullPath -Raw))
}

# Load main XAML
$window = Import-Xaml 'UI\App.xaml'

# Load resource dictionary and merge it into the window's resources
$styles = Import-Xaml 'UI\Styles.xaml'
$window.Resources.MergedDictionaries.Add( $styles )

# Show window
$null = $window.ShowDialog()

UI\App.xaml:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Hello World" Height="150" Width="300"
        WindowStartupLocation="CenterScreen">
    
    <Grid Margin="10">
        <Label Content="Hello World" 
               FontSize="24" 
               HorizontalAlignment="Center" 
               VerticalAlignment="Center"/>
    </Grid>
</Window>

UI\Styles.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="Label">
        <Setter Property="FontWeight" Value="Bold"/>
    </Style>
</ResourceDictionary>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.