Help us understand the problem. What is going on with this article?

MaterialDesignInXAMLToolkitのDialogでコマンドのバインディングが外れてしまう

More than 3 years have passed since last update.

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は呼び出し元となるのでバインディングが正しく行われます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away