UserControl托管在Panel中

时间:2012-08-22 09:10:28

标签: wpf

我花了很多时间来解决这个问题。我在wpf中有自定义用户控件,它有10个按钮的工具栏。此工具栏添加在Panel(winform面板)panel.Controls.Add(usercontrol)中。我想要的是,从Panel回复MouseLeave事件。 我已经尝试过panel.MouseLeave + = MouseLeaveEvent,但事件没有引发。没有引发任何事件(MouseMove等)。是否有任何解决方案,如何制作,MouseLeave事件将被提出? 非常感谢。

修改

这是代码。

CustomToolbar = new AxisMediaControlToolbarViewModel(this);
                    var toolbarView = new AxisMediaControlToolbarView { ViewModel = CustomToolbar };
                    var elementHost = new ElementHost { Dock = DockStyle.Fill, Child = toolbarView };
                    toolbarPanel.Controls.Add(elementHost);

2 个答案:

答案 0 :(得分:0)

其中一个原因可能是您的面板背景未设置。

如果你没有设置背景,那么控件应该是"它的区域不需要处理"实际上它是透明的,因为它没有绘制。然而,它有更多的后果:它的区域不仅没有被绘制,而且它也没有被跟踪,即鼠标事件。

对于初学者,请尝试设置Background =" Transparent"。它可能没什么意义,因为它已经是透明的,但这样Panel控件将具有背景,如果没有其他问题,它可能会立即开始看到鼠标事件。

编辑:quickexample:

UserControl.xaml

<UserControl x:Class="UserControlMouse.MyButtonPanel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             Background="LightBlue"
             Tag="You will never see this message">

    <StackPanel Margin="20" Background="LightGray"
                MouseEnter="handler_MouseEnter" MouseMove="handler_MouseMove" MouseLeave="handler_MouseLeave"
                Tag="StackPanel">
        <StackPanel.Resources>
            <Style TargetType="Border">
                <Setter Property="Margin" Value="2" />
                <Setter Property="Padding" Value="5" />
                <Setter Property="Background" Value="Gray" />
            </Style>
            <Style TargetType="TextBlock">
                <Setter Property="TextAlignment" Value="Center" />
                <Setter Property="Background" Value="WhiteSmoke" />
            </Style>
        </StackPanel.Resources>

        <Button Content="#1" MaxWidth="80" Tag="Button#1" />
        <Button Content="#2" MaxWidth="80" Tag="Button#2"
                MouseEnter="handler_MouseEnter" MouseMove="handler_MouseMove" MouseLeave="handler_MouseLeave"
                />
        <Button Content="#3" MaxWidth="80" Tag="Button#3" />
        <Button Content="#4" MaxWidth="80" Tag="Button#4" />
        <Button Content="#5" MaxWidth="80" Tag="Button#5"
                MouseEnter="handler_MouseEnter" MouseMove="handler_MouseMove" MouseLeave="handler_MouseLeave"
                />
        <Button Content="#6" MaxWidth="80" Tag="Button#6" />
        <Button Content="#7" MaxWidth="80" Tag="Button#7" />
        <Button Content="#8" MaxWidth="80" Tag="Button#8" />

        <TextBlock Margin="0,20,0,0" Tag="Comment TextBlock #1">
            <Run Text="Sender was: " />
            <Run Text="{Binding ReportingControl}" />
        </TextBlock>
        <TextBlock Tag="Comment TextBlock #2">
            <Run Text="Source was: " />
            <Run Text="{Binding ContainerControl}" />
        </TextBlock>
        <TextBlock Tag="Comment TextBlock #3">
            <Run Text="Now you are in: " />
            <Run Text="{Binding ControlUnderMouse}" />
        </TextBlock>

        <UniformGrid Columns="3" Tag="indicator UniformGrid">
            <Border Visibility="{Binding Visib_OnEnter}" Tag="indicator border #1">
                <TextBlock Text="Enter" />
            </Border>
            <Border Visibility="{Binding Visib_OnMove}" Tag="indicator border #2"
                    MouseEnter="handler_MouseEnter" MouseMove="handler_MouseMove" MouseLeave="handler_MouseLeave">
                <TextBlock Text="Move" />
            </Border>
            <Border Visibility="{Binding Visib_OnLeave}" Tag="indicator border #3">
                <TextBlock Text="Leave" />
            </Border>
        </UniformGrid>
    </StackPanel>

</UserControl>

usercontrol.xaml.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace UserControlMouse
{
    public partial class MyButtonPanel : UserControl
    {
        private SimpleDataObject theData = new SimpleDataObject();

        public MyButtonPanel()
        {
            InitializeComponent();
            this.DataContext = theData;
        }

        private const int COUNTER_LAG = 20;

        private int counter_enter = 0;
        private void handler_MouseEnter(object sender, MouseEventArgs e)
        {
            counter_enter = counter_mouse;

            theData.Visib_OnEnter = System.Windows.Visibility.Visible;
            theData.Visib_OnMove = System.Windows.Visibility.Hidden;
            theData.Visib_OnLeave = System.Windows.Visibility.Hidden;

            theData.ReportingControl = makeDescriptionOfControl(sender);
            theData.ContainerControl = makeDescriptionOfControl(e.Source);
            theData.ControlUnderMouse = makeDescriptionOfControl(null);
        }

        private int counter_mouse = 0;
        private void handler_MouseMove(object sender, MouseEventArgs e)
        {
            ++counter_mouse;

            if (counter_mouse > counter_enter + COUNTER_LAG) theData.Visib_OnEnter = System.Windows.Visibility.Hidden;
            theData.Visib_OnMove = System.Windows.Visibility.Visible;
            if (counter_mouse > counter_leave + COUNTER_LAG) theData.Visib_OnLeave = System.Windows.Visibility.Hidden;

            theData.ReportingControl = makeDescriptionOfControl(sender);
            theData.ContainerControl = makeDescriptionOfControl(e.Source);
            theData.ControlUnderMouse = makeDescriptionOfControl(null);
        }

        private int counter_leave = 0;
        private void handler_MouseLeave(object sender, MouseEventArgs e)
        {
            counter_leave = counter_mouse;

            theData.Visib_OnEnter = System.Windows.Visibility.Hidden;
            theData.Visib_OnMove = System.Windows.Visibility.Hidden;
            theData.Visib_OnLeave = System.Windows.Visibility.Visible;

            theData.ReportingControl = makeDescriptionOfControl(sender);
            theData.ContainerControl = makeDescriptionOfControl(e.Source);
            theData.ControlUnderMouse = makeDescriptionOfControl(null);
        }

        private string makeDescriptionOfControl(object uiobj)
        {
            if (uiobj == null)
                return "???";

            string text = uiobj.GetType().Name;

            var fe = uiobj as FrameworkElement;
            if (fe != null && fe.Tag != null)
                text += " (" + (string)((FrameworkElement)uiobj).Tag + ")";

            return text;
        }
    }

    public class SimpleDataObject : DependencyObject
    {
        public string ControlUnderMouse { get { return (string)GetValue(ControlUnderMouseProperty); } set { SetValue(ControlUnderMouseProperty, value); } }
        public static readonly DependencyProperty ControlUnderMouseProperty = DependencyProperty.Register("ControlUnderMouse", typeof(string), typeof(SimpleDataObject), new UIPropertyMetadata("???"));

        public string ReportingControl { get { return (string)GetValue(ReportingControlProperty); } set { SetValue(ReportingControlProperty, value); } }
        public static readonly DependencyProperty ReportingControlProperty = DependencyProperty.Register("ReportingControl", typeof(string), typeof(SimpleDataObject), new UIPropertyMetadata("???"));

        public string ContainerControl { get { return (string)GetValue(ContainerControlProperty); } set { SetValue(ContainerControlProperty, value); } }
        public static readonly DependencyProperty ContainerControlProperty = DependencyProperty.Register("ContainerControl", typeof(string), typeof(SimpleDataObject), new UIPropertyMetadata("???"));

        public Visibility Visib_OnEnter { get { return (Visibility)GetValue(Visib_OnEnterProperty); } set { SetValue(Visib_OnEnterProperty, value); } }
        public static readonly DependencyProperty Visib_OnEnterProperty = DependencyProperty.Register("Visib_OnEnter", typeof(Visibility), typeof(SimpleDataObject), new UIPropertyMetadata(Visibility.Hidden));

        public Visibility Visib_OnMove { get { return (Visibility)GetValue(Visib_OnMoveProperty); } set { SetValue(Visib_OnMoveProperty, value); } }
        public static readonly DependencyProperty Visib_OnMoveProperty = DependencyProperty.Register("Visib_OnMove", typeof(Visibility), typeof(SimpleDataObject), new UIPropertyMetadata(Visibility.Hidden));

        public Visibility Visib_OnLeave { get { return (Visibility)GetValue(Visib_OnLeaveProperty); } set { SetValue(Visib_OnLeaveProperty, value); } }
        public static readonly DependencyProperty Visib_OnLeaveProperty = DependencyProperty.Register("Visib_OnLeave", typeof(Visibility), typeof(SimpleDataObject), new UIPropertyMetadata(Visibility.Hidden));
    }
}

示例窗口

<Window x:Class="UserControlMouse.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:UserControlMouse"
        Title="MainWindow" Height="350" Width="525">
    <Grid Background="Red">
        <my:MyButtonPanel Margin="10" />
    </Grid>
</Window>

请运行并玩它。

  • 观察事件是如何触发的,以及哪些控件可以看到它们。请注意SENDER和SOURCE如何更改
  • 请注意,SENDER始终是相同的,是鼠标捕获的根源。它是改变的来源
  • 请注意,只有按钮#2和按钮#5报告ENTER / LEAVE (他们有直接处理程序,其他人没有!)
  • 请注意,其他控件可以检测到&#39;使用鼠标移动即使他们没有鼠标处理程序 - 你可以获得没有任何鼠标捕获集的源事件
  • 检查OriginalSource(最后一个文本行) - 这是直接在鼠标下的控件 - 通常它不是你想要注意的控件,因为它是一些&#34; leaf控件&#34;从一些模板或样式..

答案 1 :(得分:0)

this thread中提到的原因很多:

  • 设置UserControl的背景
  • 让Canvas成为焦点
  • 了解RenderTransforms

修改

我做了一个测试,只要WPF元素没有覆盖Panel,它就能正常工作。鼠标必须直接在面板上生成事件。 DockStyle.Fill可能是您遇到问题的原因。