Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

April Update for WPF on .NET Core 3.0 #607

Open
grubioe opened this issue Apr 18, 2019 · 14 comments

Comments

Projects
None yet
9 participants
@grubioe
Copy link
Collaborator

commented Apr 18, 2019

April Update for WPF on .NET Core 3.0

Last December, Scott Guthrie and Kevin Gallo announced that Windows Presentation Foundation (WPF), Windows Forms and WinUI would be open sourced. .NET Core 3.0 Preview 1 added support for building client apps using WPF, Windows Forms, and XAML Islands. We apologize that the WPF repository has been a little quiet, but the WPF team here at Microsoft has been hard at work at the follow items:

  1. We onboarded to the Arcade SDK based Build infrastructure
  2. The WPF project template has been made available
  3. We recently open sourced PresentationBuildTasks along with Microsoft.NET.Sdk.WindowsDesktop!
  4. We’re defining the overall test approach for WPF in a GitHub world

This work was foundational and will help us as we continue with open sourcing remaining WPF components. If you’re interested in the nitty gritty details of what we’ve been doing, take a look below.

Going Forward

As we move towards the .NET Core 3.0 General Availability (GA) we will post more regular updates to this repository. For the next few months, our plan is to:

  • Continue porting the WPF component list to this repo
  • Port regression tests so that validation against new Pull Requests can be automated

Community Contributions

We know that the community is eager to contribute and we thank you for your contributions and engagement to date!

Our primary focus for the initial .NET Core 3.0 release for WPF is to achieve parity with .NET Framework. Priority will be given to contributions that align with that goal. The most help that we need right now is on bug fixes that specifically target parity between .NET Core and .NET Framework.

You can learn more from our contributing guidelines. If you have questions, suggestions, or concerns, please let us know.

Details about onboarding the Arcade SDK

The Arcade SDK offers several benefits for products that build as part of NET Core. When the WPF team adopted this SDK for our builds, we realized some work needed to be done.

WPF was one of the first teams to onboard and build native C++ vcxproj based projects (as against CMake etc. projects) within the Arcade SDK ecosystem. This resulted in some focused work to ensure that C++ related properties and targets are appropriately tuned to ensure MSBuild just worked to build WPF with the same compiler, linker etc. settings that it has been historically built with.

We also realized that the default infrastructure in place for NuGet packaging – which is quite adequate for most projects - was insufficient for the needs of WPF given the fact that we produce native assemblies in the mix.

In addition to this, we also produce transport packages out of the WPF repository that contain the WPF .NET Core assemblies (like System.Xaml.dll, WindowsBase.dll), the native-RID specific assemblies (like wpfgfx_cor3.dll, PresentationNative_cor3.dll), reference assemblies (ref\WindowsBase.dll, ref\System.Xaml.dll), and satellite (resource) assemblies (like cs\System.Xaml.resources.dll, de\System.Xaml.resources.dll).

This fact is in itself not unique to WPF – all .NET Core repositories generate transport packages – but WPF’s unique composition involving RID-specific native assemblies necessitated us to customize the packaging process to suit our needs.

Currently, we publish the following transport packages to the https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json feed. These can be viewed using NuGet Package Explorer (which, BTW, has been ported to WPF on .NET Core 3.0!):

  • Microsoft.DotNet.Wpf.GitHub
    o runtime.win-x64.Microsoft.DotNet.Wpf.GitHub
    o runtime.win-x86.Microsoft.DotNet.Wpf.GitHub
  • Microsoft.DotNet.Wpf.DncEng
    o runtime.win-x64.Microsoft.DotNet.Wpf.DncEng
    o runtime.win-x86.Microsoft.DotNet.Wpf.DncEng
  • Microsoft.DotNet.Wpf.ProjectTemplates
  • Microsoft.NET.Sdk.WindowsDesktop

And since WPF has two repositories (one on GitHub with the open-sourced projects, and another one internal within Microsoft), we realized that coherence in the way we build things was important. To achieve this, we have centralized all our build props/targets and published it as an MSBuild SDK onto the same NuGet feed - Microsoft.DotNet.Arcade.Wpf.Sdk.

Note: All of these transport packages are intended for internal use by the .NET Core build systems and repos only and should not be consumed directly for any other purpose.
In addition to onboarding native C++ projects and building transport packages right, we also undertook some work to build C++/CLI assemblies. WPF has two notable C++/CLI based assemblies – PresentationCore.dll and System.Printing.dll.

Note: In terms of build dependencies, PresentationBuildTasks and System.Xaml can be built independently, WindowsBase requires only System.Xaml as a dependency, PresentationCore requires WindowsBase & System.Xaml, and so on. Nearly all of the remaining WPF assemblies require System.Xaml, WindowsBase, and PresentationCore. In short, PresentationCore is far in front of our build dependency chain, and we had to ensure that a build system that we open-source can handle builds for PresentationCore.dll, as well as for other C++/CLI .NET Core DLL effectively.

Many of you are probably aware that there is currently no support for building C++/CLI in .NET Core. In Dev16.0 (aka Visual Studio 2019), the C++ team has added limited capability (note: I didn’t write “support”) for compiling C++/CLI assemblies targeting .NET Core. For more details on how this works in the WPF codebase, please dig into Wpf.Cpp.props/Wpf.Cpp.targets and search for /clr:netcore. (If you try to use this today, it will probably not work for you due to a bug – please wait until Visual Studio 2019 Preview 2 comes out).

This limited support for C++/CLI has no SDK support yet. In other words, we couldn’t just take a C++/CLI vcxproj project that targeted .NET Framework and retarget it to .NET Core – the underlying NuGet support for discovering .NET Core references and a myriad of other build targets just didn’t exist. We worked with several colleagues in the .NET and C++ teams to build our own limited support for discovering the right NuGet references during build (see CppCliHelper in Wpf.Cpp.targets)

Over the years, WPF codebase had accumulated a number of cycles between some of the assemblies. The team never really noticed them because our builds depended on reference-assemblies from the previous builds (ref-assemblies that were checked in with sources in binary form).

In our .NET Core codebase, we do not check-in any binaries and require everything to be built from sources. In order to do this right, we spent some effort analyzing the dependencies between various assemblies and ensured that our build used project-references exclusively. Wherever we couldn’t break a cycle, we created small (and scoped) hand-crafted synthetic ref-assembly projects that could stand-in for the real one.

These “cycle-breakers” (there are 8 of these at last count) haven’t moved over to GitHub yet, but here is one illustrative example that is used to build PresentationUI.csproj. We found that PresentationFramework required PresentationUI to build, and PresentationUI required PresentationFramework (thus a cycle). We isolated just the small subset of types from PresentationFramework that were needed to build PresentationUI and put it into a special-purpose project that acts as a build-time cycle-breaker helper. This type of refactoring also helps prevents additional types from being added to these cycles, and will allow us to decide upon how to remove these cycles in the future.

dotnet-wpf-int/src/Microsoft.DotNet.Wpf/cycle-breakers/PresentationUI/PresentationUI.internals.cs

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ------------------------------------------------------------------------------
// Changes to this file must follow the http://aka.ms/api-review process.
// ------------------------------------------------------------------------------

using System.Runtime.CompilerServices;
using MS.Internal.PresentationCore;

[assembly:InternalsVisibleTo(BuildInfo.PresentationFramework)]

// This is the minimum set of surface area required to enable PresentationFramework to build.

namespace MS.Internal.Documents.Application
{
    internal sealed partial class DocumentStream
    {
        internal static readonly string XpsFileExtension;
    }

    internal partial struct DocumentApplicationState
    {
        private int _dummyPrimitive;
        public DocumentApplicationState(double zoom, double horizontalOffset, double verticalOffset, int maxPagesAcross) { throw null; }
        public double HorizontalOffset { get { throw null; } }
        public int MaxPagesAcross { get { throw null; } }
        public double VerticalOffset { get { throw null; } }
        public double Zoom { get { throw null; } }
    }
}

namespace MS.Internal.Documents
{
    internal sealed partial class DocumentApplicationDocumentViewer : System.Windows.Controls.DocumentViewer
    {
        public static System.Windows.Input.RoutedUICommand RequestSigners { get { throw null; } }
        public static System.Windows.Input.RoutedUICommand ShowRMCredentialManager { get { throw null; } }
        public static System.Windows.Input.RoutedUICommand ShowRMPermissions { get { throw null; } }
        public static System.Windows.Input.RoutedUICommand ShowRMPublishingUI { get { throw null; } }
        public static System.Windows.Input.RoutedUICommand ShowSignatureSummary { get { throw null; } }
        public static System.Windows.Input.RoutedUICommand Sign { get { throw null; } }
        public MS.Internal.Documents.Application.DocumentApplicationState StoredDocumentApplicationState { get { throw null; } set { } }
        public void SetUIToStoredState() { }
    }
    
    internal partial class FindToolBar : System.Windows.Controls.ToolBar //, System.Windows.Markup.IComponentConnector
    {
        public FindToolBar() { }
        public bool DocumentLoaded { set { } }
        public bool FindEnabled { get { throw null; } }
        public bool MatchAlefHamza { get { throw null; } }
        public bool MatchCase { get { throw null; } }
        public bool MatchDiacritic { get { throw null; } }
        public bool MatchKashida { get { throw null; } }
        public bool MatchWholeWord { get { throw null; } }
        public string SearchText { get { throw null; } }
        public bool SearchUp { get { throw null; } set { } }
        public event System.EventHandler FindClicked { add { } remove { } }
        public void GoToTextBox() { }
    }
}

@grubioe grubioe added this to the Preview milestone Apr 18, 2019

@vatsan-madhavan vatsan-madhavan pinned this issue Apr 18, 2019

@dotMorten

This comment has been minimized.

Copy link
Collaborator

commented Apr 19, 2019

Thank you for being so open about the progress. It helps understand why things have seemingly been moving so slow. The above makes it clear there's lots to do, and nothing has been moving slow after all :-)

@raffaeler

This comment has been minimized.

Copy link
Collaborator

commented Apr 19, 2019

Any chance to get rid of the C++/CLI in favor of xlang instead?

@weltkante

This comment has been minimized.

Copy link

commented Apr 19, 2019

@RafaelEr how would that even work? C++/CLI connects native and .NET in a way thats otherwise not possible (i.e. the same PE image contains both native and managed code). Are you saying xlang is intending to be a cross platform replacement for C++/CLI? Otherwise it's not really worth it, C++/CLI is something unique and I'd really want to have it available to me as a tool.

Anyways, I'd rather have something working soon instead of waiting for xlang to become mature enough to do the job. There's a point of WPF using C++/CLI for its renderer, because its the most appropriate tool to do the job at the time. Before even considering replacing WPF components I'd prefer if they finished the open sourcing process. One step at a time please.

@thomasclaudiushuber

This comment has been minimized.

Copy link
Contributor

commented Apr 19, 2019

Wow!!! Thanks @grubioe , I love this transparency. And it makes it very clear that we see here on GitHub just the tip of the huge iceberg, while you're building behind the scenes the foundation to bump the whole iceberg out of the water to push it into the high performance fridge called .NET Core.

As a long-time WPF fan and WPF developer, I can only say that I love what I've seen so far, and that I'm super excited about the work you do. I want to take the opportunity here to send out a huge THANK YOU to the whole team. Keep it up, the community is super excited, I'm super excited.

@raffaeler

This comment has been minimized.

Copy link
Collaborator

commented Apr 19, 2019

@weltkante Before downvoting, do you know what xlang is?
I am not against tweaking the current C++/CLI to make it work, but on the long run, I am not in favor of C++/CLI at all.

@weltkante

This comment has been minimized.

Copy link

commented Apr 19, 2019

@raffaeler yes I took a look and it doesn't seem to fullfill the purpose of C++/CLI does, they are orthogonal features. The whole point of C++/CLI is to allow native/managed code coexist in a mixed mode assembly, deeply integrating with each other. The point of xlang seems to be an abstraction so you can port a specific source code implementation to other languages and platforms. Porting the WPF rendering backend to other languages or environments doesn't provide additional value because the C++/CLI part it is almost exclusively about interop with native components, other than that it doesn't have much implementation value you could translate. DX11 is doing the rendering, DirectWrite the text, Direct2D the geometry, etc. and xlang clearly states on its front page it will not cover/port OS APIs.

Anyways my downvote was not even primarily based on xlang not being appropriate, it was mostly because its not the appropriate time and place to suggest replacing a component. They are very much behind in open sourcing WPF and I'd rather want to have the original WPF ported to core and open sourced, so I can work with my existing codebase, than them delaying everything while rewriting the rendering engine in their private repository, and then open sourcing something not related anymore at all to what I've been working with previously.

@raffaeler

This comment has been minimized.

Copy link
Collaborator

commented Apr 19, 2019

@welkante It looked to me that your downvote happened before reading about xlang.

C++/CLI will never be able to be cross platform. If the codebase will ever be ported on Linux (from MS or any future 3rd parties fork), C++/CLI will be one of the greatest blockers. The xlang project is born to be natively cross-platform and can abstract any C++ codebase better than any other solution.

Also, C++/CLI is a dialect, something that will never be adopted from gcc or clang. The C++ language is living an historical moment where there is a big convergence about the level standard to be adopted. Going back in disparities among various compiler implementations is a huge step back.

Producing IL is annother interesting point. What is the future for C++/CLI given the potential changes that may be introduced in the future? Starting from .NET Core 3 there are disparities with .NET Framework in terms of language features (ref stuff in 7.x) and APIs that can be used (for example netstandard 2.1 will not be implemented in .NET Framework).

Said that, I was asking for the future, given that the xlang .NET binding still doesn't exist. The patch that we heard on this announcement is the best option in the short terms, but looks definitely like a tweak.
For the reasons I cited above, I don't see how it can guarantee a future to the WPF codebase.

Notes:

  • the thread started with an announcement on what is happening, therefore I believe my comment is relevant
  • my comment wasn't about stopping the release to the public of the source code therefore, again, I don't see the reason for the downvote.
@zwcloud

This comment has been minimized.

Copy link

commented Apr 19, 2019

The whole point of C++/CLI is to allow native/managed code coexist in a mixed mode assembly,

I'm curious, why unsafe C# was not used when WPF was designed? I think unsafe C# code is powerful enough for native/managed interaction. I have used DirectWrite/OpenGL with unsafe C# without any C++ or C++/CLI code and it works well.

Also I think many kind people would like to help rewrite those C++/CLI code with unsafe C#.

Cannot wait for DUCE to become open-source.

@thomasclaudiushuber

This comment has been minimized.

Copy link
Contributor

commented Apr 19, 2019

@raffaeler I think your comments are as relevant as the other comments made here. But what @weltkante said is relevant too and makes sense from my point of view. And I think this is important:

I'd rather have something working soon instead of waiting for xlang to become mature enough to do the job ...One step at a time please.

Yep, I agree.

@raffaeler I upvoted your comment, as I like the discussion about this topic, but I think it would be great to have this discussion about C++/CLI and xlang in a separate issue. The issue could then be flagged as a question and design-discussion, as there are great labels for that: https://github.com/dotnet/wpf/labels

So, if you agree, @raffaeler, I would really appreciate it if you could write down your thoughts in an issue and then link to it from here. Then everybody could discuss that topic there and it doesn't get lost in an "announcement issue". Just my 2 cents.

@raffaeler

This comment has been minimized.

Copy link
Collaborator

commented Apr 19, 2019

@thomasclaudiushuber I never said to wait for xlang. As I wrote before, C++/CLI can be a short term solution but I can't see how it can be a long-term solution.
The reason why I wrote here is because I am really scared of any project using C++/CLI for the reasons I wrote.
In any case, I have no problem in opening a different issue/question on this.

@Symbai

This comment has been minimized.

Copy link

commented Apr 20, 2019

When I heard WPF is going open source I was super excited and really happy. But then seeing no activity made me wonder if this was just a low priority project. But now I'm really glad seeing this announcement, even if its just a "we're still working on it". Seeing all the amazing projects on github and how the community can bring things together, there is so much potential for WPF to benefit when you let people bring their ideas in.

Sorry that I don't have something useful to contribute rather than saying thanks.

@lupj

This comment has been minimized.

Copy link

commented Apr 28, 2019

Is there a cross-platform plan?

@thomasclaudiushuber

This comment has been minimized.

Copy link
Contributor

commented Apr 28, 2019

@lupj Cross-platform is not in the current plan. While .NET Core 3 is a cross-platform framework, WPF and WinForms will be Windows-only, and they are built on top of .NET Core 3.

Read a bit more about the plan here in the contributing.md file. Quote from this file:

We also do not intend to accept contributions that provide cross-platform implementations for Windows Forms or WPF.

This makes it clear that the plan for .NET Core 3 is to port the two UI stacks to .NET Core. The current plan is not to make these two UI stacks cross-platform. Both stacks have dependencies on Windows.

But you're not the first person asking this question. :)

There is a closed issue Make WPF cross-platform (MacOS and Linux support). It'll answer your question about the current plan.

My thoughts:
I really look forward that I can use the greatest new features of C# and .NET Core in my WPF and WinForms applications. That's why I love this project of porting both UI stacks to .NET Core. It means that you can use all the innovation that happens in .NET Core in your WPF and WinForms apps. Running for example multiple versions side-by-side is just awesome.

But the plan that WPF and WinForms are not cross-platform doesn't mean that I as a .NET and XAML developer don't dream of something like a .NET Core and XAML-based cross-platform UI Framework that you can use to build desktop applications for Windows, Linux, and MacOs. We have Xamarin, which is imo focused mainly on mobile with Android and iOS (but it can desktop too), we have the web-based Blazor, and we have for Windows Desktop UWP, WPF, and WinForms, all Windows-only. But we don't have the write-once-run-anywhere .NET Core based cross-platform Desktop UI stack (There are 3rd party projects focusing on cross-platform UI).

But when you look at .NET right now, you can see that with .NET Core 3, .NET Standard 2.1, WPF, WinForms, XAML Islands (Hosting UWP in WPF/WinForms), Xamarin, Blazor, and many other things like ML.NET, a lot is going on in the .NET world.

I can only say that I'm super happy and excited to be a .NET developer and that I strongly believe that Microsoft is doing the right thing with the current plan for WPF and WinForms: Focusing on porting WPF and WinForms as Windows-only libraries to .NET Core.

Back to topic
Cross-platform is not in the current plan.

As a long-time WPF, UWP, and XAML developer, I shared my thoughts, and I hope this helps that
we don't have to start a discussion again on this topic. Let's focus on finding and solving issues to help the .NET Team porting WPF/WinForms to .NET Core.

This doesn't mean that it wasn't a great question @lupj.

@lindexi

This comment has been minimized.

Copy link
Contributor

commented Apr 28, 2019

Is there a cross-platform plan?

Try use https://github.com/AvaloniaUI/Avalonia/ and CSHTML5 (C#/XAML for HTML5)

@svick svick referenced this issue May 4, 2019

Open

Support mixed-mode assemblies #18013

3 of 4 tasks complete

@grubioe grubioe added this to Approved-Assigned in .NET Core 3.0 May 10, 2019

@grubioe grubioe removed this from Approved-Assigned in .NET Core 3.0 May 10, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.