Closed wongjiahau closed 6 years ago
Hey yes...
I have thought about this, and I think something that could scan ANY XAML library and lists styles and locations of those styles would be useful, and a good start...
To achieve this, I think we can use the XamlWriter class.
And also we can load XAML at run time using the code below.
string text = @"<TextBlock Text='test' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' />";
// Convert to stream
// You can also just stream the xaml from a file, using a FileStream
MemoryStream stream = new MemoryStream(ASCIIEncoding.UTF8.GetBytes(text));
// Convert to object
TextBlock block = (TextBlock)System.Windows.Markup.XamlReader.Load(stream);
//... now you can put that TextBlock somewhere, for example in your main Window
Furthermore, we can use AvalonEdit to highlight the XAML code when displaying them in the demo.
The big drawback to using the XamlWriter class is that you get the run-time representation of the object. This can get rather large since you can easily end up with a huge amount of XAML that you did not expect. Something simple like this:
<Button Style="{StaticResource MaterialDesignFlatButton}" />
Ends up writing out all of the elements in the style in addition to the button. If someone is expecting to simply Copy and Paste this XAML it could quickly get out of hand.
Since I think the idea result is to display the original logical tree. I am thinking that a solution that parses the BAML and displays that information. Though this is not completely trivial itself. Sure we can go through and load the BAML, but this comes with its own challenges.
Something along the lines of this:
var assembly = Assembly.GetEntryAssembly();
var resourceStream = assembly.GetManifestResourceStream(assembly.GetName().Name + ".g.resources");
if (resourceStream == null) return;
var resourceReader = new ResourceReader(resourceStream);
foreach (var dictionaryEntry in resourceReader.OfType<DictionaryEntry>()
.Where(de => de.Key is string name &&
name.EndsWith(".baml", StringComparison.InvariantCultureIgnoreCase) && de.Value is Stream))
{
Baml2006Reader reader = new Baml2006Reader((Stream)dictionaryEntry.Value);
while (reader.Read())
{
//TODO?
}
}
Loading Xaml from the currently executing assembly can have problems since it will load it into the running application. Loading the Xaml this way it will try to load into the running application which causes error due to duplication. This also does not fully solve the problem of linking the UI element back to its corresponding Xaml, but that seems like something that should be solvable.
As an alternative we could attempt to process the Baml as part of the compile process. I have some experience building Fody weavers. This would be similar to how GitLink works. I would envision doing something like:
Thoughts?
The other question is how to surface this in the demo application. I do like the idea of using the AvalonEdit control to get nice syntax highlighting, though I am not sure how/where that should be displayed in the UI.
@Keboo Yes, that is a big drawback, so currently, I am thinking of doing it the other way round. That is to write the XAML code in CS, then load it into the UI using XamlReader. I'll show it to you the demo soon.
Hi guys,
Another thought, just parsing the XAML outside of the demo, and spitting out some HTML is worth considering, bedside then we can just add a list to the wiki/website somewhere.
Let's not forget that XAML is just XML so possibly just xpath or linq2xml would get that done.
Second attempt to solve this problem :
Thank you for reading this. I hope you'll review it.
Please refer to this repository for the full code.
Hi @wongjiahau this looks very interesting. When I have a little more time I will look over it more closely.
Third attempt to solve this problem :
Thank you for reading this. I hope you'll review it. Please refer to this repository for the full code of XamlDisplayerPanel.
Hi @wongjiahau I am trying to run the code, but it appears that one of the references in CodeDisplayer is a local file.
<Reference Include="XamlStyler.Core">
<HintPath>..\..\..\XamlStyler\XamlStyler.Core\bin\Release\XamlStyler.Core.dll</HintPath>
</Reference>
Is this something that can be checked in?
@Keboo Sorry for the problem, I had already fixed that by including the .dll in the repository in the following directory :
Displaying-XAML/WpfApplication1/CodeDisplayer/DependencyPackage/XamlStyler.Core.dll
There are still problem apparently because XamlStyler.Core.dll is referencing another 2 dlls, I'm triyng to fix this problem by using Costura.Fody [FIXED]
I just tried this out, (via download link in gitter) and it is awesome.
This makes the demo app 100x more useful and saves me loads of time.
Great work!
@AmitBhatnagar24 Thanks :) @ButchersBoy I hope you will include this feature in the next release, as this will greatly reduces the gulf of execution. Most of the users (for example myself), whenever I want to use a type of control, I can picture it in my mind, but I can't really remember its code, therefore I'll need the catalog to easily get the code I want.
Hello @wongjiahau , Cool stuff. I'll try it with one of my application written in wpf.
varun
@wongjiahau This doesn't seem to work anymore - crashes upon launch. I'm suspecting its failing when trying to pull the latest demo code source from GitHub?
@AmitBhatnagar24 Sorry for the inconvenience causes, because I've updated the source code yesterday, try download the latest version here
This has been implemented in the demo app.