CommunityToolkit / Microsoft.Toolkit.Win32

ARCHIVE - This repository contained XAML Islands wrapper controls and tooling for XAML Islands with WinUI 2, see readme for more info about XAML Islands with WinUI 3 and the WindowsAppSDK.
https://aka.ms/windowsappsdk
Other
383 stars 89 forks source link

Using Xaml islands in WPF Class Library #269

Closed ghost closed 4 years ago

ghost commented 4 years ago

Description of the problem

First of all, please excuse me if this is not the right forum for my question. I'm relatively new to asking coding related questions.

My scenario is that I'm working on a so called "deskband" (a toolbar that attaches to the windows taskbar). Using this project as a base, I've modified it and added a system volume indicator. The project is a WPF Class Library targeting Net Core 3.1. By using regsvr32 xxx.dll it becomes visible in the taskbar and as part of the shell (explorer.exe).

Now what I'm trying to achieve is that when you click the volume indicator it should open a small popup window with a volume slider. As i'm trying to mimic the standard Windows 10 volume slider I need the window to be UWP style with dark transparent Acrylic backdrop.

Steps to reproduce

1) Adding the Microsoft.Toolkit.Wpf.UI.XamlHost package through NuGet Manager. 2) Created a User Control that I'm attaching to a new window as the icon is clicked and modified the xaml like this, using a "ProgressRing" for testing purpose:

<UserControl x:Class="WPFUI.VolumeSlider"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
             xmlns:local="clr-namespace:WPFUI"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
            <xamlhost:WindowsXamlHost ChildChanged="WindowsXamlHost_ChildChanged"
                            InitialTypeName="Windows.UI.Xaml.Controls.ProgressRing" />
    </Grid>
</UserControl>

3) Added this for the backcode:

private void WindowsXamlHost_ChildChanged(object sender, EventArgs e)
        {
            var host = (Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost)sender;
            var progressRing = (Windows.UI.Xaml.Controls.ProgressRing)host.Child;
            progressRing.IsActive = true;
        }

This compiles but when running I get this exception when trying to open the window: System.TypeLoadException: Could not find Windows Runtime type 'Microsoft.Toolkit.Win32.UI.XamlHost.IXamlMetadataContainer'.

Putting that same code in a standard WPF Core App worked fine. However I had to also add a manifest.app file containing this:

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>

            <!-- Windows 10 -->
            <maxversiontested Id="10.0.18358.0"/>
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />

        </application>
    </compatibility>

</assembly>

However as this is a .dll I can't use the "application" tag and attach the manifest file.

The question

So my question is essentially: Is it at all possible to use Xaml Islands from a .dll, or does it have to be an executable application?

Environment

NuGet Package(s): Microsoft.Toolkit.Wpf.UI.XamlHost

Package Version(s): 6.0.1

Project .NET Version:

Windows 10 Build Number:

Visual Studio

ghost commented 4 years ago

Hello spacelime, thank you for opening an issue with us!

I have automatically added a "needs triage" label to help get things started. Our team will analyze and investigate the issue, and escalate it to the relevant team if possible. Other community members may also look into the issue and provide feedback 🙌

michael-hawker commented 4 years ago

@spacelime, I believe there's two options:

1) You to just create a standard UWP based control, and the implementing application developer would use XAML Islands to include it in their app. 2) You look at the 'wrappers' we've provided here in the toolkit which provide an easier interface for WPF developers to leverage a UWP control via XAML Islands.

I don't know how well this type of use-case is documented though, and it'll probably get easier with the new WinUI 3 world. @marb2000 can you comment more on this?

ghost commented 4 years ago

@spacelime, I believe there's two options:

  1. You to just create a standard UWP based control, and the implementing application developer would use XAML Islands to include it in their app.
  2. You look at the 'wrappers' we've provided here in the toolkit which provide an easier interface for WPF developers to leverage a UWP control via XAML Islands.

I don't know how well this type of use-case is documented though, and it'll probably get easier with the new WinUI 3 world. @marb2000 can you comment more on this?

Thank you. Yes I've tested out option 1 with regular WPF Net Core 3.1 apps and it's working. However I'm not sure if it's possible to apply to a Class Library as in this case?

michael-hawker commented 4 years ago

@spacelime our main control repo exposes class libraries which developers can just use in XAML Islands (though we're doing more work in our 7.0 release (there's a preview out) to better support some differences in threading models with the new DispatcherQueue).

ghost commented 4 years ago

@spacelime our main control repo exposes class libraries which developers can just use in XAML Islands (though we're doing more work in our 7.0 release (there's a preview out) to better support some differences in threading models with the new DispatcherQueue).

I'm sorry but I think I wasn't clear enough in my question. When I talked about class libraries, what I meant is if it's possible to build my own WPF class library and then to implement UWP elements in it via Xaml Island.

What I've done is to create a new Net Core 3.1 Class Library project in VS2019, added WPF support so that it displays a window. Now I'm trying to add a Xaml Island to that window. Is this even possible at the moment?

marb2000 commented 4 years ago

Q: Is it possible to build my own WPF class library and then to implement UWP elements in it via Xaml Island. A: Yes it's possible, but the app still needs to specify the maxversiontested Id="10.0.18358.0" in the manifest. Also, we recommend to follow the custom control approach. Hope this helps.

hansmbakker commented 4 years ago

I think the point of the topic starter was that you cannot modify explorer.exe or the windows shell.

In the custom control tutorial, the head end project needs to reference a XamlApplication class and it needs to be packaged.

The topic starter's question whether you can do that for a control library dll where you don't have control over the application that consumes your control library.

marb2000 commented 4 years ago

Thanks for bringing more clarity to the question @hansmbakker. Correct, you cannot modify explorer.exe or the windows shell, so that no maxversiontested, no XAML Islands.

Just you clarification. You don't need to packaged your app, unpackaged apps are also supported in XAML Islands,