dhq_boiler
@dhq_boiler

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

[WPF]ContentControl.MouseDoubleClickイベントが機能しない

お世話になっております。

ベクターグラフィックスドローイングツール boiler's Graphics を開発しております。

2021-09-26.png

解決したいこと

描画した図形をダブルクリックした時に、プロパティのLeft、Top、Width、Heightを編集できる新しいダイアログを開くように実装しようとしています。手始めに、四角形を描画した後、四角形をダブルクリックすると新しいダイアログが表示されるように実装してみます。

発生している問題・エラー

ダブルクリックイベントを持っていないコントロールで判定を拾う HOS Co.,Ltd.
https://www.hos.co.jp/blog/20200331/

上記のサイトにダブルクリックイベントを拾うにはContentControlを使うとできるよと書いてあったので、そのように実装してみました。

以下、四角形の実装。

Resources/DesignerItems/RectangleDesignerItemDataTemplate.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:convereter="clr-namespace:boilersGraphics.Converters"
                    xmlns:helper="clr-namespace:boilersGraphics.Helpers"
                    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
                    xmlns:viewModel="clr-namespace:boilersGraphics.ViewModels">
    <convereter:ToSolidColorBrushConverter x:Key="solidColorBrushConverter" />
    <DataTemplate DataType="{x:Type viewModel:NRectangleViewModel}">
        <ContentControl>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDoubleClick">
                    <i:InvokeCommandAction Command="{Binding MouseDoubleClickCommand}" />
                    <!--<helper:DebugAction />-->
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <Path Data="{Binding PathGeometry.Value}"
                  Fill="{Binding FillColor.Value, Converter={StaticResource solidColorBrushConverter}}"
                  IsHitTestVisible="False"
                  Stretch="Fill"
                  Stroke="{Binding EdgeColor.Value, Converter={StaticResource solidColorBrushConverter}}"
                  StrokeThickness="{Binding EdgeThickness.Value}" />
        </ContentControl>
    </DataTemplate>
</ResourceDictionary>

MouseDoubleClickCommandを実装したクラスは下記の通りです。

ViewModels/NRectangleViewModel.cs

using boilersGraphics.Helpers;
using boilersGraphics.Views;
using Prism.Ioc;
using Prism.Services.Dialogs;
using Prism.Unity;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System;
using System.Reactive.Linq;
using System.Windows.Media;
using System.Windows.Shapes;

namespace boilersGraphics.ViewModels
{
    public class NRectangleViewModel : DesignerItemViewModelBase
    {
        public NRectangleViewModel()
            : base()
        {
            Init();
        }

        public NRectangleViewModel(double left, double top, double width, double height)
            : base()
        {
            Init();
            Left.Value = left;
            Top.Value = top;
            Width.Value = width;
            Height.Value = height;
        }

        public NRectangleViewModel(double left, double top, double width, double height, double angleInDegrees)
            : this(left, top, width, height)
        {
            RotationAngle.Value = angleInDegrees;
            Matrix.Value.RotateAt(angleInDegrees, 0, 0);
        }

        public NRectangleViewModel(int id, IDiagramViewModel parent, double left, double top)
            : base(id, parent, left, top)
        {
            Init();
        }

        public ReactiveCommand MouseDoubleClickCommand { get; } = new ReactiveCommand();

        private void Init()
        {
            this.ShowConnectors = false;
            EnablePathGeometryUpdate.Value = true;
            MouseDoubleClickCommand.Subscribe(x =>
            {
                var dialogService = new DialogService((App.Current as PrismApplication).Container as IContainerExtension);
                IDialogResult result = null;
                //新しいダイアログオープン!!!!
                dialogService.Show(nameof(DetailRectangle), new DialogParameters() { { "ViewModel", (NRectangleViewModel)this.Clone() } }, ret => result = ret);
                if (result != null)
                {
                    var viewModel = result.Parameters.GetValue<NRectangleViewModel>("ViewModel");
                    this.Left.Value = viewModel.Left.Value;
                    this.Top.Value = viewModel.Top.Value;
                    this.Width.Value = viewModel.Width.Value;
                    this.Height.Value = viewModel.Height.Value;
                }
            })
            .AddTo(_CompositeDisposable);
        }
        :
    }
}

ダブルクリックした時にダイアログを開く処理と新しいダイアログ自体を実装したのですが、ダブルクリックした時に新しいダイアログが開きません。

どうしてでしょうか。なぜMouseDoubleClickイベントが発火しないのかわかる方いらっしゃいますか?

ちなみに新しいダイアログは下記のようになっています。
Left, Top, Width, Heightがテキストボックスで変更できるようになっています。あっ、OKボタンつけ忘れてた!

2021-10-23.png

該当するソースコード

ブランチ:v4.5
コミット:ca73820

ソースコードの規模はめちゃくちゃでかいと思います。気をつけてください。

自分で試したこと

EventTriggerのEventNameをMouseDoubleClickからMouseDownに変更しても、マウスダウン時にダイアログが表示されることはありませんでした。どうやらi.Interactions.Triggersが機能していないような気がします。

Resources/DesignerItems/RectangleDesignerItemDataTemplate.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:convereter="clr-namespace:boilersGraphics.Converters"
                    xmlns:helper="clr-namespace:boilersGraphics.Helpers"
                    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
                    xmlns:viewModel="clr-namespace:boilersGraphics.ViewModels">
    <convereter:ToSolidColorBrushConverter x:Key="solidColorBrushConverter" />
    <DataTemplate DataType="{x:Type viewModel:NRectangleViewModel}">
        <ContentControl>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDown"> <!--MouseDownに変更してもイベント発火しない-->
                    <i:InvokeCommandAction Command="{Binding MouseDoubleClickCommand}" />
                    <!--<helper:DebugAction />-->
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <Path Data="{Binding PathGeometry.Value}"
                  Fill="{Binding FillColor.Value, Converter={StaticResource solidColorBrushConverter}}"
                  IsHitTestVisible="False"
                  Stretch="Fill"
                  Stroke="{Binding EdgeColor.Value, Converter={StaticResource solidColorBrushConverter}}"
                  StrokeThickness="{Binding EdgeThickness.Value}" />
        </ContentControl>
    </DataTemplate>
</ResourceDictionary>

Microsoft.Xaml.Behaviors.Wpfを使っているのは変わらないので、何がいけないんだろう。まったくわかりません。

誰か助けてください。よろしくお願いいたします。

0

2Answer

とりあえず代替案として、コンテキストメニューから新しいダイアログを表示するという案を採用しました。動作イメージは下記の通りです。

show_detail_rectangle_dialog.gif

0Like

下記が、ContentControlのMouseDoubleClickのサンプルです。

MainWindow.xaml
<Window x:Class="WpfAppSample1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfAppSample1"
        Title="MainWindow" Height="300" Width="400">
    <Grid>
        <ContentControl MouseDoubleClick="MouseDoubleClickCommand">
            <Path Fill="LemonChiffon" Stroke="Black" StrokeThickness="1">
                <Path.Data>
                    <RectangleGeometry Rect="50,50,100,100" />
                </Path.Data>
            </Path>
        </ContentControl>
    </Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Input;

namespace WpfAppSample1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void MouseDoubleClickCommand(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show("ダブルクリック");
        }
    }
}

下記が、InvokeCommandActionのサンプルです。

MainWindow.xaml
<Window x:Class="WpfAppSample1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:local="clr-namespace:WpfAppSample1"
        Title="MainWindow" Height="300" Width="400" x:Name="mainWindow">
    <Grid>
        <ContentControl>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDoubleClick">
                    <i:InvokeCommandAction Command="{Binding MouseDoubleClickCommand,ElementName=mainWindow}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <Path Fill="LemonChiffon" Stroke="Black" StrokeThickness="1">
                <Path.Data>
                    <RectangleGeometry Rect="50,50,100,100" />
                </Path.Data>
            </Path>
        </ContentControl>
    </Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Input;

namespace WpfAppSample1
{
    public partial class MainWindow : Window
    {
        private ICommand _mouseDoubleClickCommand = null;

        public ICommand MouseDoubleClickCommand
        {
            get
            {
                if (_mouseDoubleClickCommand == null)
                {
                    _mouseDoubleClickCommand = new Class1();
                }
                return _mouseDoubleClickCommand;
            }
        }

        public MainWindow()
        {
            InitializeComponent();
        }
    }

    class Class1 : ICommand
    {
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            MessageBox.Show("ダブルクリック");
        }
    }
}

何かの役に立てば幸いです。

0Like

Your answer might help someone💌