http://materialdesigninxaml.net/
https://github.com/ButchersBoy/MaterialDesignInXamlToolkit
Googleが押してるマテリアルデザインをWPFなどで実現できるフレームワークです。
http://neue.cc/2015/09/10_515.html
個人的にWPFのアプリを作る機会ができて有名な方が紹介してたので使ってみました。
基本的にnugetでインストールしてもいいしgithubからプロジェクト持ってきても問題ないし素晴らしいです。
最新のコードでは直ってます。
https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/commit/00f73ab51648da33b1f3512aaab070a29e1e057c
使っていて修正した部分があったのでメモ。
DialogHostにて
<Button Command="{x:Static wpf:DialogHost.OpenDialogCommand}" HorizontalAlignment="Right" Margin="5,5,30,5" DockPanel.Dock="Bottom" Style="{StaticResource MaterialDesignFloatingActionAccentButton}">
<Button.CommandParameter>
<StackPanel Margin="16">
<TextBlock>保存しますか?</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
<Button Style="{StaticResource MaterialDesignFlatButton}"
IsDefault="True"
Margin="0 8 8 0"
Command="{Binding SaveCommand}" CommandParameter="{Binding Model}">
保存
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}"
IsCancel="True"
Margin="0 8 8 0"
Command="wpf:DialogHost.CloseDialogCommand">
CANCEL
</Button>
</StackPanel>
</StackPanel>
</Button.CommandParameter>
保存
</Button>
こんな感じでXAMLを書いておくと、一番近くのDialogHostのDialogが呼ばれます。
このXAMLではボタンコマンドでDialogをオープンしてCommandParameterでダイアログのFrameworkElementを送っています。
こうすると、DialogHostがパラメータのエレメントを使ってダイアログを開いてくれます。
ダイアログの中にて保存処理コマンドにBindingをしているのですが、DialogHostが同一のDataContext範囲内にある場合は問題ありませんが、DialogHostが別のDataContext下にある場合、コマンドのバインディングが外れてしまいます。
private void OpenDialogHandler(object sender, ExecutedRoutedEventArgs executedRoutedEventArgs)
{
if (executedRoutedEventArgs.Handled) return;
var dependencyObject = executedRoutedEventArgs.OriginalSource as DependencyObject;
if (dependencyObject != null)
{
_attachedDialogOpenedEventHandler = GetDialogOpenedAttached(dependencyObject);
_attachedDialogClosingEventHandler = GetDialogClosingAttached(dependencyObject);
}
if (executedRoutedEventArgs.Parameter != null)
{
AssertTargetableContent();
DialogContent = executedRoutedEventArgs.Parameter;
}
SetCurrentValue(IsOpenProperty, true);
executedRoutedEventArgs.Handled = true;
}
実際のOpen時の処理部分になります。
DialogContentにParameterをセットしている部分なのですが、ParameterのDataContextにはDialogHostのDataContextが設定されています。
よってCommandのbindingは外れた状態となってしまいます。
なのでDialogContentを設定した後に以下を追加します。
var dialogHomeSource = executedRoutedEventArgs.Source as FrameworkElement;
if (dialogHomeSource?.DataContext != null
&& !DataContext.Equals(dialogHomeSource.DataContext))
{
var dialogElement = DialogContent as FrameworkElement;
if (dialogElement != null)
{
dialogElement.DataContext = dialogHomeSource.DataContext;
}
}
これでDialogのDataContextは呼び出し元となるのでバインディングが正しく行われます。