使用动态参数在样式中绑定元素名称.重用样式

本文关键字:样式 元素 绑定 参数 动态 | 更新日期: 2023-09-27 18:32:17

我有一个问题。我在 WPF 设计器 (XML) 中为 TextBlock 创建了一个样式。在两个图像控件中的任何一个上触发 IsMouseOver 事件后,我的 textBlocks 会更改其位置。此样式用于某些文本块。

<Style x:Key="movingTextBlocksStyle" TargetType="{x:Type TextBlock}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding ElementName=image1, Path=IsMouseOver}" Value="True">
            <Setter Property="RenderTransform">
                <Setter.Value>
                    <TranslateTransform/>
                </Setter.Value>
            </Setter>
            <DataTrigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" From="0" To="-125"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
        </DataTrigger>
        <DataTrigger Binding="{Binding ElementName=image2, Path=IsMouseOver}" Value="True">
            <Setter Property="RenderTransform">
                <Setter.Value>
                    <TranslateTransform/>
                </Setter.Value>
            </Setter>
            <DataTrigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" From="0" To="-125"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
        </DataTrigger>
    </Style.Triggers>
</Style>

此样式将用作:

<TextBlock x:Name="textBlock1" Style="{StaticResource movingTextBlocksStyle}"/>
<TextBlock x:Name="textBlock2" Style="{StaticResource movingTextBlocksStyle}"/>

我的问题是我想将这种样式重用于另一个 textBlocks:textBlock3 和 textBlock4,其中"绑定元素名称"不同,例如 image3 和 image4。我想过,如果有任何可能用某种类型的动态参数或参数重用这种风格,那就太好了。我搜索任何解决方案仅作为 xml 代码,没有任何 C#(我将 C# 与 WPF 一起使用)或转换器实现。

提前谢谢。

使用动态参数在样式中绑定元素名称.重用样式

下面是纯 XAML 解决方案:

在数组中收集文本块所依赖的所有控件,并将其设置为数据上下文:

<Image x:Name="image1"/>
<Image x:Name="image2"/>
<TextBlock Style="{StaticResource movingTextBlocksStyle}">
    <TextBlock.DataContext>
        <x:Array Type="system:Object">
            <x:Reference>image1</x:Reference>
            <x:Reference>image2</x:Reference>
        </x:Array>
    </TextBlock.DataContext>
</TextBlock>

您需要记住相应地更改TextBlock属性上的所有绑定,因为不再继承数据上下文。然后在样式定义中使用相应的数组索引绑定:

<DataTrigger Binding="{Binding [0].IsMouseOver}" Value="True">...</DataTrigger>
...
<DataTrigger Binding="{Binding [1].IsMouseOver}" Value="True">...</DataTrigger>

system:前缀命名空间为 clr-namespace:System;assembly=mscorlib

您可以

定义附加属性,这些属性将保存TextBox所依赖的控件,如下所示(我将仅使用一个属性来保持简短):

static class Helper
{
    public static object GetImage(DependencyObject obj)
    {
        return (object)obj.GetValue(ImageProperty);
    }
    public static void SetImage(DependencyObject obj, object value)
    {
        obj.SetValue(ImageProperty, value);
    }
    public static readonly DependencyProperty ImageProperty =
        DependencyProperty.RegisterAttached(
            "Image",
            typeof(object),
            typeof(Helper),
            new PropertyMetadata(null));
}

然后,在数据触发器中,使用附加属性进行绑定:

...
<DataTrigger Binding="{Binding Path=(local:Helper.Image).IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
...

最后,将属性值设置为TextBlock所依赖的控件:

<Image x:Name="image1"/>
...
<TextBlock local:Helper.Image="{Binding ElementName=image1}"
           Style="{StaticResource movingTextBlocksStyle}"/>

此解决方案不是纯粹的 XAML - 它需要一些代码隐藏来定义附加的属性,但我怀疑是否有一种优雅的方法可以完全避免它。