📚
Windows App SDK の ContentDialog の幅を Window の幅に追従させたい
先日、以下のような記事を書きました。
これの欠点としては ContentDialog
の表示中に Window
のサイズを変えても表示時点で指定したプロパティの値を元に ContentDialog
のサイズが決まってしまうという点です。例えば常に Window
サイズの 80% くらいで ContentDialog
を表示したいという動作はできません。ちょっとコードを書かないといけないです。
ロジックとしては Window
のサイズ変更時に ContentDialog
の Content
に設定しているコントロールの幅を変えてやれば OK です。例えば以下のように:
var dialogContent = new TextBlock
{
Text = "Hello world" ,
Width = Bounds.Width * 0.8,
};
void sizeChanged(object _, WindowSizeChangedEventArgs args)
{
dialogContent.Width = args.Size.Width * 0.8;
}
SizeChanged += sizeChanged;
var dialog = new ContentDialog
{
XamlRoot = Content.XamlRoot,
Content = dialogContent,
CloseButtonText = "Close",
};
await dialog.ShowAsync();
SizeChanged -= sizeChanged;
こうすると以下のような結果になります。
いい感じですね。毎回毎回 ContentDialog
を表示するところに、こういう処理を書くのはだるいので適当にクラスにまとめてしまったりするといいと思います。
例えばこんな感じに:
class FollowWindowWidthBehavior : IDisposable
{
private readonly FrameworkElement? _content;
private readonly Window _window;
private readonly Func<double, double> _calcDialogWidth;
private bool _disposedValue;
public FollowWindowWidthBehavior(ContentDialog contentDialog, Window window, Func<double, double> calcDialogWidth)
{
_window = window;
_calcDialogWidth = calcDialogWidth;
_content = contentDialog.Content as FrameworkElement;
if (_content != null)
{
_window.SizeChanged += Window_SizeChanged;
_content.Width = calcDialogWidth(_window.Bounds.Width);
}
}
private void Window_SizeChanged(object sender, WindowSizeChangedEventArgs args)
{
_content!.Width = _calcDialogWidth(args.Size.Width);
}
public void Dispose()
{
_window.SizeChanged -= Window_SizeChanged;
}
}
これを使うとこんな感じで書けます。
var dialog = new ContentDialog
{
XamlRoot = Content.XamlRoot,
Content = new TextBlock { Text = "Hello world" },
CloseButtonText = "Close",
};
using (new FollowWindowWidthBehavior(dialog, this, windowWidth => windowWidth * 0.8))
{
await dialog.ShowAsync();
}
思い付きで作ったので、もっといい感じに書けるようにまとめられるかもしれません。
Discussion