如何在 Border Style 中编写 WPF DataTrigger 以及如何在 Setter 中查找元素?

How to write WPF DataTrigger within Border Style and how to Find Element in Setter?

我需要一个 WPF DataTrigger 来实现 Border 的鼠标悬停功能。边框包含一个按钮,最初它的可见性是折叠的。按钮应仅在鼠标悬停时可见,否则会折叠。

<Border Width="100" Height="30" HorizontalAlignment="Center" VerticalAlignment="Top" Background="#FFF2FFC6" Margin="0,20,0,0">
    <Button x:Name="btn" Content="iApp" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Visibility="Collapsed" />
    <Border.Style>
        <Style TargetType="Border">
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True">
                    <Setter TargetName="btn" Property="Visibility" Value="Visible"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
</Border>

Note: I need only DataTrigger. Don't suggest Event Trigger.

在这里我无法找到 TargetName,它会产生构建错误“错误 1 ​​无法识别名称 "btn"

  1. TragetName 不能在 Style.Triggers 中使用。应该用在ControlTemplete.Triggers.
  2. 你可以这样写代码(未测试)。

添加你的命名空间xaml

     xmlns:converter="clr-namespace:yours coverter's namespace"

在您的资源中添加转换器

     <UserControl.Resources>
           <converter:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
     </UserControl.Resources>

这是你的边框:

     <Border x:Name="m_Border" Margin="0,20,0,0">
     <Button x:Name="btn" Content="iApp"  Visibility="{Binding  IsMouseOver,ElementName=m_Border,Converter="{StaticResource BooleanToVisibilityConverter},ConverterParameter=Normal}"}" />
    </Border> 
  1. 使用这个转换器

      public enum BooleanToVisibilityConverterType
      {
            /// <summary>
            /// Normal
            /// </summary>
            Normal = 1,
    
            /// <summary>
            /// Reverse
            /// </summary>
            Reverse = 2
       }
    
      public class BooleanToVisibilityConverter : IValueConverter
      {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                 var targertValue = false;
    
             if (value == null)
             {
                 throw new Exception("BooleanToVisibilityConverter - Convert Error");
             }
             else if (!Boolean.TryParse(value.ToString(), out targertValue))
             {
                 throw new Exception("BooleanToVisibilityConverter - Convert Error");
             }
             else
             {
                 var parameterValue = BooleanToVisibilityConverterType.Normal;
    
                 if (parameter != null)
                 {
                     Enum.TryParse<BooleanToVisibilityConverterType>(parameter.ToString(), out parameterValue);
                 }
    
                 if (parameterValue == BooleanToVisibilityConverterType.Reverse)
                 {
                return targertValue ? Visibility.Collapsed : Visibility.Visible;
                 }
                 else
                 {
                     return targertValue ? Visibility.Visible : Visibility.Collapsed;                    
                 }
             }
         }
    
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var targetValue = Visibility.Collapsed;
    
        if (value == null)
        {
            throw new Exception("BooleanToVisibilityConverter - ConvertBack Error");
        }
        else if (!Enum.TryParse<Visibility>(value.ToString(), out targetValue))
        {
            throw new Exception("BooleanToVisibilityConverter - ConvertBack Error");
        }
        else
        {
            var parameterValue = BooleanToVisibilityConverterType.Normal;
    
            if (parameter != null)
            {
                Enum.TryParse<BooleanToVisibilityConverterType>(parameter.ToString(), out parameterValue);
            }
    
            if (parameterValue == BooleanToVisibilityConverterType.Reverse)
            {
                return targetValue == Visibility.Visible ? false : true;
            }
            else
            {
                return targetValue == Visibility.Visible ? true : false;
            }
        }
    }
    

TargetName 主要在控件模板中使用,而不仅仅是在样式中使用。

来自MSDN

You can set this property to the name of any element within the scope of where the setter collection (the collection that this setter is part of) is applied. This is typically a named element that is within the template that contains this setter.

此外,为了满足您的需要,您应该将触发器设置为 Button 而不是 Border

   <Border x:Name="border" Width="100" Height="30" HorizontalAlignment="Center" VerticalAlignment="Top" Background="#FFF2FFC6" Margin="0,20,0,0">
        <Button x:Name="btn" Content="iApp" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" >
            <Button.Style>
                <Style>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ElementName=border, Path=IsMouseOver}" Value="false">
                            <Setter Property="Button.Visibility" Value="Collapsed"></Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
    </Border>