sourcechord / FluentWPF

Fluent Design System for WPF.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MahApps.Metroとの併用でObject reference not set to an instance of an object.が発生する

logue opened this issue · comments

https://sourcechord.hatenablog.com/entry/2017/12/26/021149
に書いてある方法でMahAppsに組み込もうとしましたがうまく動きません。

<mah:MetroWindow x:Class="MahAppsTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:fw="clr-namespace:SourceChord.FluentWPF;assembly=FluentWPF"
    xmlns:local="clr-namespace:MahAppsTest"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="525"
    Height="350"
    fw:AcrylicWindow.Enabled="True"
    fw:AcrylicWindow.ShowTitleBar="False"
    Background="Transparent"
    BorderThickness="1"
    GlowBrush="{DynamicResource AccentColorBrush}"
    mc:Ignorable="d">
    <Grid>
    </Grid>
</mah:MetroWindow>

以下のようなエラーが発生します。

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=MahApps.Metro
  スタック トレース:
   at MahApps.Metro.Controls.MetroWindow.OnApplyTemplate()
   at System.Windows.FrameworkElement.ApplyTemplate()
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Interop.HwndSource.SetLayoutSize()
   at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
   at System.Windows.Interop.HwndSource.set_RootVisual(Visual value)
   at System.Windows.Window.SetRootVisual()
   at System.Windows.Window.SetRootVisualAndUpdateSTC()
   at System.Windows.Window.SetupInitialState(Double requestedTop, Double requestedLeft, Double requestedWidth, Double requestedHeight)
   at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
   at System.Windows.Window.CreateSourceWindowDuringShow()
   at System.Windows.Window.SafeCreateWindowDuringShow()
   at System.Windows.Window.ShowHelper(Object booleanBox)
   at System.Windows.Window.Show()
   at Prism.PrismApplicationBase.OnInitialized()
   at Prism.PrismApplicationBase.InitializeInternal()
   at Prism.PrismApplicationBase.OnStartup(StartupEventArgs e)
   at System.Windows.Application.<.ctor>b__1_0(Object unused)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run()
   at MahAppsTest.App.Main()

  この例外は、最初にこの呼び出し履歴 
    [外部コード] でスローされました

自作のクラスで手動でアクリル化させたところ動いたのでFluentWPF側の問題だと思います。

AcrylicBase.cs.txt
MetroAcrylicWindow.cs.txt

@logue
FluentWPFとMahApps.Metroはそれぞれどのバージョンを使っていますか?
上記ブログに書いていた手順ですが、かなり古いバージョンでの手順となっております。
現在のFluentWPFやMahApps.Metroでは使えなくなっています。
(ブログ中に書いているAcrylicWindow.ShowTitleBarというプロパティですが、現在のFluentWPFでは使えなくなったプロパティです。)

FluentWPF0.9.0とMahApps.Metro2.4.7で、以下のようなコードで試してもらえますか?

<mah:MetroWindow x:Class="MahAppsNetCore.MainWindow"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:local="clr-namespace:MahAppsNetCore"
                 xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
                 xmlns:fw="clr-namespace:SourceChord.FluentWPF;assembly=FluentWPF"
                 mc:Ignorable="d"
                 Title="MainWindow" Height="450" Width="800"
                 fw:AcrylicWindow.Enabled="True"
                 fw:AcrylicWindow.AcrylicWindowStyle="None">
    <Grid>
        <TextBlock Text="Hello World!!" />
        <Button Margin="30" Content="Button" Width="75" Height="35" />
    </Grid>
</mah:MetroWindow>

こんな風に表示できるかと思います。
image

現在のMahApps.Metroとの併用では、ウィンドウ最大化時の表示が崩れるなど若干の問題が残ってます。
この辺は、次回のバージョンアップで対応しようと思います。
その際に、MahApps.Metro併用のサンプルコードも、合わせて更新しますね。

ありがとうございます。

どうやら、MahApps(と、おそらくMaterialDesignInXamlToolkit)は、この行が必須みたいですね。

fw:AcrylicWindow.AcrylicWindowStyle="None"

これを追加したら動きました。

はい、MahApps.MetroのようなUIフレームワークと併用する上では、fw:AcrylicWindow.AcrylicWindowStyle="None"の指定が必要です。
この指定をすると、FluentWPFはタイトルバーなどの描画をせず、全面がコンテンツ描画領域のウィンドウとなります。
FluentWPF、MahApps.Metroともに、ウィンドウのタイトルバーを独自に描画するフレームワークですので、この指定をしておかないと、双方のライブラリで二重にタイトルバーが描画されてしまいます。