62120


前提で、MVVMでダイアログ表示を行おうとしています。ダイアログ表示をするため添付ビヘイビアとしてDialogAttachedBehaviorを使用しています。Viewのイベントは使用しません。  
MainView.xamlにDatatemplateとしてダイアログのViewを指定しています。  
現状、1つのダイアログを表示することはできています。  
しかし、Datatemplateの複数指定の方法が分からず、複数のダイアログの表示ができません。  
そのため、複数のDatatemplateの指定方法を教えてください。

以下サイトを参考にしました。  
<http://sourcechord.hatenablog.com/entry/2014/04/06/234443>

MainView.xaml

[code]

    <Window x:Class="Apps.DialogApp.App.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:Apps.DialogApp.App"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid local:DialogAttachedBehavior.CloseCommand="{Binding CloseDialogCommand}"
          local:DialogAttachedBehavior.WindowViewModel="{Binding DialogVM}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="70*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions >
            <RowDefinition Height="6*"/>
            <RowDefinition Height="6*"/>
            <RowDefinition Height="6*"/>
        </Grid.RowDefinitions>
        <local:DialogAttachedBehavior.WindowTemplate>
            <DataTemplate>
                <local:DialogView/>
            </DataTemplate>
        </local:DialogAttachedBehavior.WindowTemplate>
        <TextBox Text="{Binding Message}" Grid.Row="0"/>
        <Button Command="{Binding OpenDialogCommand}" Content="Open" Grid.Row="1"/>
        <Button Command="{Binding CloseDialogForCodeCommand}" Content="ダイアログ閉じる" Grid.Row="2"/>
    </Grid>
    
[/code]

MainWindowViewModel.cs

[code]

        public class MainWindowViewModel : Common.BindableBase
    {
        private string message;
        public string Message
        {
            get
            {
                return message;
            }
            set
            {
                this.message = value;
                this.RaisePropertyChanged();
            }
        }
    
        private DialogViewModel dialogVM;
        public DialogViewModel DialogVM
        {
            get
            {
                return dialogVM;
            }
            set
            {
                this.dialogVM = value;
                this.RaisePropertyChanged();
            }
        }
    
        private DelegateCommand openDialogCommand;
        public DelegateCommand OpenDialogCommand
        {
            get
            {
                return openDialogCommand = openDialogCommand ?? new DelegateCommand(OpenDialog);
            }
        }
    
        private void OpenDialog(object parameter)
        {
            this.DialogVM = new DialogViewModel() { Message = this.Message };
        }
    
        private DelegateCommand openDialogCommand2;
        public DelegateCommand OpenDialogCommand2
        {
            get
            {
                return openDialogCommand2 = openDialogCommand2 ?? new DelegateCommand(OpenDialog2);
            }
        }
    
        private void OpenDialog2(object parameter)
        {
            this.DialogVM = new DialogViewModel2() { Message = this.Message };
        }
    
        private DelegateCommand closeDialogCommand;
        public DelegateCommand CloseDialogCommand
        {
            get
            {
                return closeDialogCommand = closeDialogCommand ?? new DelegateCommand(CloseDialog);
            }
        }
    
        private void CloseDialog(object parameter)
        {
            DialogViewModel vm = parameter as DialogViewModel;
            this.Message = vm.Message; 
        }
    
        private DelegateCommand closeDialogForCodeCommand;
        public DelegateCommand CloseDialogForCodeCommand
        {
            get
            {
                return closeDialogForCodeCommand = this.closeDialogForCodeCommand ?? new DelegateCommand(CloseDialogForCode);
            }
        }
    
        private void CloseDialogForCode(object parameter)
        {
            this.DialogVM = null;
        }
    }
    
[/code]

DialogAttachedBehavior.cs(DelegateCommandはICommandを継承したクラスです)

[code]

        public class DialogAttachedBehavior
    {
        // CloseCommand
        public static DelegateCommand GetCloseCommand(DependencyObject obj)
        {
            return (DelegateCommand)obj.GetValue(CloseCommandProperty);
        }
    
        public static void SetCloseCommand(DependencyObject obj, DelegateCommand value)
        {
            obj.SetValue(CloseCommandProperty,value);
        }
    
        public static readonly DependencyProperty CloseCommandProperty =
            DependencyProperty.RegisterAttached("CloseCommand",typeof(DelegateCommand), typeof(DialogAttachedBehavior), new PropertyMetadata(null));
    
        // WindowTemplate
        public static DataTemplate GetWindowTemplate(DependencyObject obj)
        {
            return (DataTemplate)obj.GetValue(WindowTemplateProperty);
        }
    
        public static void SetWindowTemplate(DependencyObject obj, DataTemplate value)
        {
            obj.SetValue(WindowTemplateProperty, value);
        }
    
        public static readonly DependencyProperty WindowTemplateProperty =
            DependencyProperty.RegisterAttached("WindowTemplate", typeof(DataTemplate), typeof(DialogAttachedBehavior), new PropertyMetadata(null));
    
        // Window
        public static Window GetWindow(DependencyObject obj)
        {
            return (Window)obj.GetValue(WindowProperty);
        }
    
        public static void SetWindow(DependencyObject obj, Window value)
        {
            obj.SetValue(WindowProperty, value);
        }
    
        public static readonly DependencyProperty WindowProperty =
            DependencyProperty.RegisterAttached("Window", typeof(Window), typeof(DialogAttachedBehavior), new PropertyMetadata(null));
    
    
        // WindowViewModel
        public static object GetWindowViewModel(DependencyObject obj)
        {
            return (object)obj.GetValue(WindowViewModelProperty);
        }
    
        public static void SetWindowViewModel(DependencyObject obj, object value)
        {
            obj.SetValue(WindowViewModelProperty, value);
        }
    
        public static readonly DependencyProperty WindowViewModelProperty =
            DependencyProperty.RegisterAttached("WindowViewModel", typeof(object), typeof(DialogAttachedBehavior), new PropertyMetadata(null, OnWindowViewModelChanged));
    
        private static void OnWindowViewModelChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as FrameworkElement;
            if(element == null)
            {
                return;
            }
    
            var template = GetWindowTemplate(obj);
            var viewmodel = GetWindowViewModel(obj);
    
            if(template != null)
            {
                if(viewmodel != null)
                {
                    OpenWindow(element);
                }
                else
                {
                    CloseWindow(element);
                }
            }
        }
    
        private static void OpenWindow(FrameworkElement element)
        {
            var win = GetWindow(element);
            var cmd = GetCloseCommand(element);
            var template = GetWindowTemplate(element);
            var vm = GetWindowViewModel(element);
    
            if (win == null)
            {
                win = new Window()
                {
                    ContentTemplate = template,
                    Content = vm,
                    SizeToContent = SizeToContent.WidthAndHeight,
                    Owner = null
                };
    
    
                win.Closed += (s, e) =>
                {
                    if (cmd != null)
                    {
                        if (cmd.CanExecute(vm))
                        {
                            cmd.Execute(vm);
                        }
                    }
                    SetWindow(element, null);
                };
    
                SetWindow(element, win);
                // ダイアログ表示
                win.Show();
            }
            else
            {
                // 画面アクティブ化(前面に)
                win.Activate();
            }
        }
    
        private static void CloseWindow(FrameworkElement element)
        {
            var win = GetWindow(element);
    
            if(win != null)
            {
                win.Close();
                SetWindow(element, null);
            }
        }
    
        public static bool GetClose(DependencyObject obj)
        {
            return (bool)obj.GetValue(CloseProperty);
        }
    
        public static void SetClose(DependencyObject obj, bool value)
        {
            obj.SetValue(CloseProperty, value);
        }
    
        public static readonly DependencyProperty CloseProperty =
            DependencyProperty.RegisterAttached("Close", typeof(bool), typeof(DialogAttachedBehavior), new PropertyMetadata(false, OnCloseChanged ));
    
        private static void OnCloseChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var win = obj as Window;
            if(win == null)
            {
                win = Window.GetWindow(obj);
            }
    
            if (GetClose(obj))
            {
                win.Close();
            }
        }
    }
    
[/code]


CC BY-SA 4.0
2020-01-10T00:49:20.400
62119
2020-01-10T10:19:53.853
2020-01-10T10:19:53.853
32228
32228
question
c# wpf mvvm dialog
MVVMで1画面に複数ダイアログView(Datatemplate)の指定方法が知りたい


自己解決しました。  
方法としては、Datatemplateをビヘイビアで設定するのをやめて、  
MainWindow.xamlのWindow.Resorceに指定しました。  
ビヘイビア側で、Window.ResorceのDatatemplateを検索してViewModelに対応するViewを取得するようにしました。

MainView.xamlの変更した箇所

[code]

        <Window.Resources>
        <DataTemplate x:Key="DialogViewModel">
            <local:DialogView />
        </DataTemplate>
        <DataTemplate x:Key="DialogViewModel2">
            <local:DialogView2 />
        </DataTemplate>
    </Window.Resources>
    
[/code]

DialogAttachedBehavior.csの変更した箇所

[code]

            private static void OnWindowViewModelChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as FrameworkElement;
            if(element == null)
            {
                return;
            }
    
            var viewmodel = GetWindowViewModel(obj);
    
            if (viewmodel != null)
            {
                var template = element.FindResource(viewmodel.GetType().Name);
                if (template != null)
                {
                    OpenWindow(element);
                }
                else
                {
                    CloseWindow(element);
                }
            }
        }
    
        private static void OpenWindow(FrameworkElement element)
        {
            var win = GetWindow(element);
            var cmd = GetCloseCommand(element);
            var vm = GetWindowViewModel(element);
            var template = (DataTemplate)element.FindResource(vm.GetType().Name);
    
            if (win == null)
            {
                win = new Window()
                {
                    ContentTemplate = template,
                    Content = vm,
                    SizeToContent = SizeToContent.WidthAndHeight,
                    Owner = null
                };
    
    
                win.Closed += (s, e) =>
                {
                    if (cmd != null)
                    {
                        if (cmd.CanExecute(vm))
                        {
                            cmd.Execute(vm);
                        }
                    }
                    SetWindow(element, null);
                };
    
                SetWindow(element, win);
                // ダイアログ表示
                win.Show();
            }
            else
            {
                // 画面アクティブ化(前面に)
                win.Activate();
            }
        }
    
[/code]


CC BY-SA 4.0
2020-01-10T02:24:43.237
62120
2020-01-10T02:24:43.237
32228
62119
answer