Package: pymsbuild-winui
pymsbuild-winuiThis is a highly experimental and early stage extension topymsbuild. It uses the Microsoft
Windows App SDK to build GUI apps based on XAML.The sample projects intestdata/app1andtestdata/BasicPhotoViewerare currently the best starting point.Good luck!(Expressions of interest are welcome right now, but not contributions.)Quick StartIn your_msbuild.py, importWinUIExe,XamlAppandXamlPagefrompymsbuild_winui(usingimport *is okay).TheWinUIExeelement will take theXamlAppand one or moreXamlPages and generate an executable file along witha lotof
support files. The package this element goes into should contain the
Python sources and any other content, but only XAML items should be in
theWinUIExeitself.The name of theWinUIExemust match the namespaces used in the XAML
filesx:Classattributes, and must also be an importable Python
module that will contain the implementation of each page.frompymsbuildimport*frompymsbuild_winuiimport*METADATA={...}PACKAGE=Package('PhotoViewerApp',PyFile("PhotoViewer.py"),PyFile("image_info.py"),WinUIExe("PhotoViewer",XamlApp("app.xaml"),XamlPage("MainWindow.xaml"),IncludePythonRuntime=True,# these both default to True, theyIncludeAppRuntime=True,# are just here for the example),)definit_PACKAGE(tag):# WinUIExe needs to be passed the wheel tag to complete setupPACKAGE.find("PhotoViewer").init_PACKAGE(tag)In the main Python module (PhotoViewer.pyin the above example), each
XAML page must have a class with matching name and the initializer
shown below.classMainWindow:def__init__(self,view,viewmodels):...Theviewargument is a reference to the XAML instance. You should
keep this around asself.viewto use it later.Theviewmodelsargument has each defined viewmodel as an attribute.
You should now update theview.modelsdict to map your model types to
their viewmodels. This will enableview.wrap()andview.unwrap()to
work.self.view.models[image_info.ImageInfo]=viewmodels.ImageInfoself.view.models[image_info.ImagesRepository]=viewmodels.ImageRepositoryTheviewobject 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:ViewModelName="ImageInfo"><py:PropertyName="Name"Type="str"/><py:PropertyName="Path"Type="str"/></py:ViewModel><py:ViewModelName="ImageRepository"><py:PropertyName="Images"Type="list[PhotoViewer.ImageInfo]"/></py:ViewModel><py:PropertyName="ImagesRepository"Type="PhotoViewer.ImageRepository"/>Property types areverylimited, 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.Thelist[]property type defines a readonly property containing an
observable list that can contain any object type. The type specifier is
for self-documentation only, it is never verified. You cannot assign to
list properties, but can use theirappend,clear,extend,insertandreplace_allmethods to modify the contents. Note that
each update to an observable list may trigger UI updates if it has been
bound, and soreplace_allis recommended for batching updates
together.# Python list of Python objectsimages=[ImageInfo(p.name,p)forpinpaths]# Update the viewmodel with wrapped instancesviewmodel.Images.replace_all(view.wrap(i)foriinimages)Event handlers for common types will be automatically detected from
your XAML. However, it is also possible to explicitly define them in
case of needing to override the sender or argument type.<!-- Not required for these particular events, but just syntax examples! --><py:EventHandlerName="ImageClick"Sender="object"/><py:EventHandlerName="OnElementPointerEntered"EventArgs="Microsoft.UI.Xaml.Input.PointerRoutedEventArgs"/>Arguments are passed through with exactly the type they are defined as,
which mean meansenderwill 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. Theeargument will
already be usable as the type specified in theEventArgsattribute.
Event handlers found automatically will pass in the type they were
defined on.defImageClick(self,sender,e):sender=sender.as_("Microsoft.UI.Xaml.Controls.Button")...defOnElementPointerEntered(self,sender,e):...Finally, theviewobject contains any controls that were named withx:Namein 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 soText="{x:bind Message,Mode=OneWay}"is more efficient
than writingself.view.StatusControl.Text = Message.