WPF用户控件;触发器和更改其他控件

3

我创建了一个包含按钮和组合框的WPF用户控件。我想根据鼠标位置更改两者的样式,使鼠标悬停的UI元素变为黑色,另一个则变为红色。如果没有应用任何样式,则将应用默认样式。

不要担心,这个可怕的颜色方案只是为了说明概念!

在此感谢您的帮助。

XAML

<UserControl x:Class="WpfUserControlSample.ToolbarButtonCombo"
             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" 
             xmlns:local="clr-namespace:WpfUserControlSample"
             x:Name="Control"
             mc:Ignorable="d" 
             d:DesignHeight="30">    
    <UserControl.Resources>
        <Style TargetType="{x:Type local:ToolbarButtonCombo}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsButtonMouseOver}" Value="True">
                    <Setter Property="ButtonStyle" Value="Black"/>
                    <Setter Property="ComboStyle" Value="Red"/>                    
                </DataTrigger>
                <!--
                <DataTrigger Binding="{Binding IsComboMouseOver}" Value="True">
                    <Setter Property="ButtonStyle" Value="Red"/>
                    <Setter Property="ComboStyle" Value="Black"/>
                </DataTrigger>
                -->
            </Style.Triggers>
        </Style>
    </UserControl.Resources>
    <StackPanel Orientation="Horizontal" Height="30">
        <Button Name="btn" Background="{Binding ButtonStyle,ElementName=Control,Mode=OneWay}">
            Test
        </Button>
        <ComboBox Name="cmb" Background="{Binding ComboStyle,ElementName=Control,Mode=OneWay}"></ComboBox>
    </StackPanel>
</UserControl>

代码后台:

namespace WpfUserControlSample
{
    public partial class ToolbarButtonCombo : UserControl, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        }  
        public ToolbarButtonCombo()
        {
            InitializeComponent();
            btn.MouseEnter += new MouseEventHandler(btn_MouseChanged);
            btn.MouseLeave += new MouseEventHandler(btn_MouseChanged);
        }
        void btn_MouseChanged(object sender, MouseEventArgs e)
        {
            OnPropertyChanged("IsButtonMouseOver");
        }


        public bool IsButtonMouseOver
        {
            get { return btn.IsMouseOver; }

        }
        public static readonly DependencyProperty IsButtonMouseOverProperty =
            DependencyProperty.Register("IsButtonMouseOver", typeof(string), typeof(ToolbarButtonCombo), new PropertyMetadata("false"));

        public string ButtonStyle { get; set; }
        public static readonly DependencyProperty ButtonStyleProperty =
            DependencyProperty.Register("ButtonStyle", typeof(string), typeof(ToolbarButtonCombo));

        public string ComboStyle { get; set; }
        public static readonly DependencyProperty ComboStyleProperty =
            DependencyProperty.Register("ComboStyle", typeof(string), typeof(ToolbarButtonCombo));    
    }
}

1
如果您在IsButtonMouseOver中设置断点或在返回之前添加一些Console.WriteLine,您会发现它从未被调用,我经验不太丰富,但这部分对我来说似乎很奇怪,我认为您没有正确连接到实际的IsMouseOver。如果可以的话,我个人会直接使用IsMouseOver属性的普通触发器,但我是一个新手,不知道如何更改现有的代码。祝好运。 - Pierre
1个回答

3

有两个问题。

首先,您的DataTrigger绑定似乎不正确。它们正在查找DataContext上的IsButtonMouseOver,而不是关联控件。您需要使用:

<DataTrigger Binding="{Binding IsButtonMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
    <Setter Property="ButtonStyle" Value="Black"/>
    <Setter Property="ComboStyle" Value="Red"/>                    
</DataTrigger>

或者:

<Trigger Property="IsButtonMouseOver" Value="True">
    <Setter Property="ButtonStyle" Value="Black"/>
    <Setter Property="ComboStyle" Value="Red"/>                    
</Trigger>

另一个问题是您的IsButtonMouseOver没有正确实现。您应该这样做:
public static readonly DependencyProperty IsButtonMouseOverProperty = DependencyProperty.Register("IsButtonMouseOver",
    typeof(bool), typeof(ToolbarButtonCombo), new PropertyMetadata(false));

    public bool IsButtonMouseOver
    {
        get { return (bool)this.GetValue(IsButtonMouseOverProperty); }
        set { this.SetValue(IsButtonMouseOverProperty, value); }
    }

    void btn_MouseChanged(object sender, MouseEventArgs e)
    {
        this.IsButtonMouseOver = this.btn.IsMouseOver;
    }

或者更正确地说,将IsButtonMouseOver设置为只读依赖属性,如下所示:

private static readonly DependencyPropertyKey IsButtonMouseOverPropertyKey = DependencyProperty.RegisterReadOnly("IsButtonMouseOver",
    typeof(bool), typeof(ToolbarButtonCombo), new FrameworkPropertyMetadata(false));

public static readonly DependencyProperty IsButtonMouseOverProperty = ToolbarButtonCombo.IsButtonMouseOverPropertyKey.DependencyProperty;

public bool IsButtonMouseOver {
    get { return (bool)this.GetValue(IsButtonMouseOverProperty); }
    private set { this.SetValue(IsButtonMouseOverPropertyKey, value); }
}

您的其他属性(ButtonStyle和ComboStyle)也需要正确实现,它们的get/set方法也不受依赖属性支持。

太好了,现在我知道自己哪里出了问题。非常感谢! - Martin Clarke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接