为什么MouseLeftButtonDown不适用于我的自定义控件中的按钮但是PreviewMouseLeftButtonDown和AddHandler呢?

时间:2014-05-16 21:14:37

标签: wpf user-controls event-handling

据我所知,如果我试图将事件冒泡或隧道传输到另一个控件,那么Button会“窃取”该事件,但实际上我正在尝试调用该事件。在这些文件中不应该有任何不寻常的东西,但以下是整个事情(问题出在SearchTextBox.cs中的OnApplyTemplate中):

Generic.xaml的片段:

<SolidColorBrush x:Key="TextBoxBorder" Color="#ababab"/>
    <Style TargetType="{x:Type ui:SearchTextBox}">
        <Setter Property="AllowDrop" Value="True" />
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
        <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="LabelText" Value="Search for..." />
        <Setter Property="LabelTextColor" Value="Gray" />
        <Setter Property="Padding" Value="1" />
        <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
        <Setter Property="Stylus.IsFlicksEnabled" Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ui:SearchTextBox}">
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualHeight}" />
                            </Grid.ColumnDefinitions>

                            <Label x:Name="LabelText"
                                   Grid.Column="0"
                                   Foreground="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelTextColor}"
                                   Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelText}"
                                   Padding="0"
                                   Margin="5,0,0,0"
                                   FontStyle="Italic"
                                   VerticalAlignment="Center"
                                   Visibility="Hidden" />
                            <ScrollViewer Grid.Column="0" Panel.ZIndex="1" x:Name="PART_ContentHost" Background="{TemplateBinding Background}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Margin="5,0,0,0" Padding="0"/>
                            <Image x:Name="Image" Grid.Column="1" Visibility="Hidden" Source="search2.png" Width="15" Height="15" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                            <Button x:Name="PART_Button" Grid.Column="1" Width="15" Height="15">
                                <Border HorizontalAlignment="Center" VerticalAlignment="Center">
                                    <Image Source="searchstop.png" />
                                </Border>
                            </Button>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="Text" Value="">
                            <Setter TargetName="Image" Property="Visibility" Value="Visible" />
                            <Setter TargetName="PART_Button" Property="Visibility" Value="Hidden" />
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="Text" Value="" />
                                <Condition Property="IsFocused" Value="False" />
                            </MultiTrigger.Conditions>
                            <Setter TargetName="LabelText" Property="Visibility" Value="Visible" />
                            <Setter TargetName="PART_ContentHost" Property="Visibility" Value="Hidden" />
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

SearchTextBox.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace App
{
    public class SearchTextBox : TextBox
    {
        public static readonly DependencyProperty LabelTextProperty;
        public static readonly DependencyProperty LabelTextColorProperty;
        public static readonly DependencyProperty SearchModeProperty;
        public static readonly DependencyProperty HasTextProperty;
        private static readonly DependencyPropertyKey HasTextPropertyKey;
        public static readonly DependencyProperty SourceProperty;

        static SearchTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(SearchTextBox), new FrameworkPropertyMetadata(typeof(SearchTextBox)));

            LabelTextProperty = DependencyProperty.Register("LabelText", typeof(string), typeof(SearchTextBox));
            LabelTextColorProperty = DependencyProperty.Register("LabelTextColor", typeof(Brush), typeof(SearchTextBox));
            SearchModeProperty = DependencyProperty.Register("SearchMode", typeof(SearchMode), typeof(SearchTextBox), new PropertyMetadata(SearchMode.Instant));
            HasTextPropertyKey = DependencyProperty.RegisterReadOnly("HasText", typeof(bool), typeof(SearchTextBox), new PropertyMetadata());
            HasTextProperty = HasTextPropertyKey.DependencyProperty;
            SourceProperty = DependencyProperty.Register("Source", typeof(ImageSource), typeof(SearchTextBox));
        }

        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            base.OnTextChanged(e);
            HasText = Text.Length != 0;
        }

        public string LabelText
        {
            get { return (string)GetValue(LabelTextProperty); }
            set { SetValue(LabelTextProperty, value); }
        }

        public Brush LabelTextColor
        {
            get { return (Brush)GetValue(LabelTextColorProperty); }
            set { SetValue(LabelTextColorProperty, value); }
        }

        public SearchMode SearchMode
        {
            get { return (SearchMode)GetValue(SearchModeProperty); }
            set { SetValue(SearchModeProperty, value); }
        }

        public ImageSource Source
        {
            get { return (ImageSource)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        public bool HasText
        {
            get { return (bool)GetValue(HasTextProperty); }
            private set { SetValue(HasTextPropertyKey, value); }
        }

        public override void OnApplyTemplate()
        {
            Button b = GetTemplateChild("PART_Button") as Button;
            if (b != null)
            {
                b.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);

                // This also works
                //b.AddHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnMouseLeftButtonDown));

                // Doesn't work
                //b.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);
            }

            base.OnApplyTemplate();
        }

        private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Text = "";
        }
    }
}

1 个答案:

答案 0 :(得分:1)

尝试阅读:

http://msdn.microsoft.com/en-us/library/system.windows.uielement.mouseleftbuttondown.aspx

MouseLeftButtonDownEvent由另一个控件处理,通常由ButtonBase处理:

http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/Primitives/ButtonBase.cs#1001a15c43ab91f9(第414行)

正确的方法是使用AddHandler或PreviewMouseLeftButtonDown事件