Skip to main content

A WinUI extension for PyMSBuild

Project description

pymsbuild-winui

This is a highly experimental and early stage extension to pymsbuild. It uses the Microsoft Windows App SDK to build GUI apps based on XAML.

The sample projects in testdata/app1 and testdata/BasicPhotoViewer are currently the best starting point.

Good luck!

(Expressions of interest are welcome right now, but not contributions.)

Quick Start

In your _msbuild.py, import WinUIExe, XamlApp and XamlPage from pymsbuild_winui (using import * is okay).

The WinUIExe element will take the XamlApp and one or more XamlPages and generate an executable file along with a lot of support files. The package this element goes into should contain the Python sources and any other content, but only XAML items should be in the WinUIExe itself.

The name of the WinUIExe must match the namespaces used in the XAML files x:Class attributes, and must also be an importable Python module that will contain the implementation of each page.

from pymsbuild import *
from pymsbuild_winui import *

METADATA = {...}

PACKAGE = Package(
    'PhotoViewerApp',
    PyFile("PhotoViewer.py"),
    PyFile("image_info.py"),
    WinUIExe(
        "PhotoViewer",
        XamlApp("app.xaml"),
        XamlPage("MainWindow.xaml"),
    ),
)

def init_PACKAGE(tag):
    # WinUIExe needs to be passed the wheel tag to complete setup
    PACKAGE.find("PhotoViewer").init_PACKAGE(tag)

In the main Python module (PhotoViewer.py in the above example), each XAML page must have a class with matching name and the initializer shown below.

class MainWindow:
    def __init__(self, view, viewmodels):
        ...

The view argument is a reference to the XAML instance. You should keep this around as self.view to use it later.

The viewmodels argument has each defined viewmodel as an attribute. You should now update the view.models dict to map your model types to their viewmodels. This will enable view.wrap() and view.unwrap() to work.

    self.view.models[image_info.ImageInfo] = viewmodels.ImageInfo
    self.view.models[image_info.ImagesRepository] = viewmodels.ImageRepository

The view object also contains any properties that were defined in the XAML. Properties and viewmodels use a private XML namespace that is processed at build time.

    ...
    xmlns:py="http://schemas.stevedower.id.au/pymsbuild/winui"
    ...
    <py:ViewModel Name="ImageInfo">
        <py:Property Name="Name" Type="str" />
        <py:Property Name="Path" Type="str" />
    </py:ViewModel>
    <py:ViewModel Name="ImageRepository">
        <py:Property Name="Images" Type="list[object]" />
    </py:ViewModel>
    <py:Property Name="ImagesRepository" Type="PhotoViewer.ImageRepository" />

Property types are very limited, try to stick to primitives or other viewmodels. Notice that the viewmodel type must include the namespace, which is implicitly added to the name specified when defining it.

Event handlers must also be defined (for now), and also defined on your Python class. They are hooked up using normal XAML specifications.

    <py:EventHandler Name="ImageClick" />
    <py:EventHandler Name="OnElementPointerEntered" EventArgs="Microsoft.UI.Xaml.Input.PointerRoutedEventArgs" />

Arguments are passed through with exactly the type they are defined as, which often means sender will need to be down-cast in order to access its members. The .as_() function takes a fully qualified name as a string, and will raise if the conversion fails. The e argument will already be usable as the type specified in the EventArgs attribute.

    def ImageClick(self, sender, e):
        sender = sender.as_("Microsoft.UI.Xaml.Controls.Control")
        ...

    def OnElementPointerEntered(self, sender, e):
        ...

Finally, the view object contains any controls that were named with x:Name in the XAML. In general, it is best to avoid working with controls directly, and instead try to use XAML bindings ({x:bind}) to properties and viewmodels. All properties and viewmodels provide update notifications, and so Text="{x:bind Message,Mode=OneWay}" is more efficient than writing self.view.StatusControl.Text = Message.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymsbuild_winui-0.0.1a4.tar.gz (44.4 kB view details)

Uploaded Source

Built Distribution

pymsbuild_winui-0.0.1a4-py3-none-win32.win_amd64.whl (59.5 kB view details)

Uploaded Python 3 Windows x86 Windows x86-64

File details

Details for the file pymsbuild_winui-0.0.1a4.tar.gz.

File metadata

  • Download URL: pymsbuild_winui-0.0.1a4.tar.gz
  • Upload date:
  • Size: 44.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.6

File hashes

Hashes for pymsbuild_winui-0.0.1a4.tar.gz
Algorithm Hash digest
SHA256 4b9dc51fd396b8f92792d384164bb592010da3a836b5428217aeb9b90b1eefc3
MD5 d718f99cb465a980a36162d888f817ea
BLAKE2b-256 06683b758ea9728968294aedbc3508017c6539547a403bd1939f9c245fbffe31

See more details on using hashes here.

Provenance

File details

Details for the file pymsbuild_winui-0.0.1a4-py3-none-win32.win_amd64.whl.

File metadata

File hashes

Hashes for pymsbuild_winui-0.0.1a4-py3-none-win32.win_amd64.whl
Algorithm Hash digest
SHA256 2bc14da947157f71a0c4a6056aa4938fa8da79e0ba7bfe46021d978da9e2c798
MD5 2ff97365ae3904ecd48002e2cc22666f
BLAKE2b-256 26258ecf0632490ddc64970681634202e868cc90159879129ea4f4b0fd1cc1a9

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page