Adding BasedOn Style on App.xaml is crashing on Ap

2019-03-21 14:36发布

问题:

Adapting an project to Template10, I go into inherited styles in App.xaml are crashing.

It looks like Template10, doesn´t support inherited or extended styles. I was trying to extend SubTitleStyle from TitleStyle but I get an COM exceptions on GetXamlType in XamlTypeInfo.g.cs

My App.xaml.cs

sealed partial class App : BootStrapper
{
    public App() { InitializeComponent(); }

    public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
    {
        NavigationService.Navigate(typeof(ShellView))
        await Task.CompletedTask;
    }
}

My App.xaml

<Style x:Key="TitleStyle" TargetType="TextBlock">
    <Setter Property="Foreground" Value="{StaticResource TextTitleForeground}"/>
    <Setter Property="FontSize" Value="26"/>
    <Setter Property="TextWrapping" Value="Wrap"/>
    <Setter Property="FontWeight" Value="Medium"/>
</Style>
<Style x:Key="SubTitleStyle" TargetType="TextBlock" BasedOn="{StaticResource TitleStyle}">
    <Setter Property="Foreground" Value="{StaticResource TextForeground}"/>
    <Setter Property="FontSize" Value="20"/>
</Style>

Exception info:

Error HRESULT E_FAIL has been returned from a call to a COM component.

at System.Runtime.InteropServices.WindowsRuntime.IIterator`1.MoveNext()
at System.Runtime.InteropServices.WindowsRuntime.IteratorToEnumeratorAdapter`1.MoveNext()
at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
at Template10.Common.BootStrapper.<InitializeFrameAsync>d__77.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Template10.Common.BootStrapper.<InternalLaunchAsync>d__53.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c.<ThrowAsync>b__6_0(Object state)
at System.Threading.WinRTSynchronizationContext.Invoker.InvokeCore()

回答1:

This was deeply confounding to me. I was easily able to reproduce this. And, then, I was easily able to reproduce this without a reference to Template 10. The offending code is this block in T10:

// title
foreach (var resource in Application.Current.Resources
    .Where(x => x.Key.Equals(typeof(Controls.CustomTitleBar))))
{
    var control = new Controls.CustomTitleBar();
    control.Style = resource.Value as Style;
}

You could simplify it to this:

var a = Application.Current.Resources.ToArray();

Placed in the OnLaunched of any app's Application. Boom. The error itself comes when we are attempting to access the resource collection but only when a BasedOn style has been added to the resources.

After sitting down with the platform team to try and vindicate Template 10, everyone around the table started scratching their heads. And, that's when I realized @dachibox, you have discovered a genuine bug in the XAML platform.

Here's the only current workaround until we update Template 10.

<Page.Resources>
    <ResourceDictionary Source="..\Styles\Custom.xaml" />
</Page.Resources>

What I mean is, you do the work in the page instead of in App. So, how will we fix Template 10 without the XAML platform getting fixed? Take a look at this wonky code we will be using in Bootstrapper:

int count = Application.Current.Resources.Count;
foreach (var resource in Application.Current.Resources)
{
    var k = resource.Key;
    if (k == typeof(Controls.CustomTitleBar))
    {
        var s = resource.Value as Style;
        var t = new Controls.CustomTitleBar();
        t.Style = s;
    }
    count--;
    if (count == 0) break;
}

The error, at least, is in the iterator's count property which seems to increment instead of decrement as you iterate through it. Crazy huh? Turns out, this iteration path is not a common use case. But, that does not matter now, we've raised the flag thanks to your question here.

I'll update Template 10 with the fix sometime this week.

Best of luck, Jerry