0

我将 WPF 用于我的 C# 应用程序,在该应用程序上我有几个文本不适合的标签。我想要的是让我的文本在标签内移动,以便用户可以看到整个文本。示例:假设我的文本有 20 个字符长,我的标签只有 15 个字符的空间。我想要的是我的标签显示前 15 个字符(字符 1-15),然后在 1 秒后显示相同的字符,没有第一个但最后有另一个(所以字符 2-16)然后是下一个(字符 3-17 ) 依此类推,直到最后 15 个字符(字符 5-20),然后我希望它们从头开始(再次是字符 1-15)。

我怎样才能做到这一点 ?一种方法是(显然)使用计时器,但我确信存在更优雅的解决方案。

4

3 回答 3

2

下面是一个快速而肮脏的滚动控件的代码,一旦用户将鼠标悬停在控件上,它就会执行您想要的操作。

        <Canvas Name="brd" 
                ClipToBounds="True"
                Margin="10" 
                Height="20" Width="150" 
                Background="White"
                HorizontalAlignment="Left">
            <StackPanel Name="spl1" 
                        Orientation="Horizontal"
                        Canvas.Left="0">
                <TextBlock Name="tbk1"
                           Margin="10,0"
                           MinWidth="{Binding ElementName=brd,Path=ActualWidth}"
                           Text="A display of test text that is wider than the control."/>
                <TextBlock MinWidth="{Binding ElementName=brd,Path=ActualWidth}"
                           Margin="10,0"
                           Text="{Binding ElementName=tbk1,Path=Text}"/>
            </StackPanel>
            <Canvas.Triggers>
                <EventTrigger RoutedEvent="MouseEnter">
                    <BeginStoryboard Name="scroll">
                        <Storyboard RepeatBehavior="Forever">
                            <DoubleAnimation To="-200" Duration="0:0:4"  
                                             Storyboard.TargetName="spl1"
                                             Storyboard.TargetProperty="(Canvas.Left)" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger> 
                <EventTrigger RoutedEvent="MouseLeave">
                    <StopStoryboard BeginStoryboardName="scroll"/>
                </EventTrigger>
            </Canvas.Triggers>
        </Canvas>

为了正确操作,您需要更改一个部分,但我没有实施。<DoubleAnimation To="-200"...遗嘱需要改变。理想情况下,for 的值To将是控件ActualWidth属性的负值。tbk1这将需要一个元素绑定来获取值和一个ValueConverter使该值成为负值。

如果您不想麻烦使用转换器,您可以使该To值足够大以容纳您期望的最长文本。这会让你相当接近。

当然,您可以对此进行更多调整,以在一个动画周期结束和下一个动画周期开始时提供更平滑的过渡。

编辑

好吧,我不能让它完成一半。下面是更新后的 XAML 以实现流畅操作,以及包含的ValueConverter.

<Window.Resources>
    <Converters:ChangeSignConverter x:Key="ChangeSignConverter"/>
</Window.Resources>

        <Canvas Name="brd" 
                ClipToBounds="True"
                Margin="10" 
                Height="20" Width="150" 
                Background="White"
                HorizontalAlignment="Left">
            <StackPanel Name="spl1" 
                        Margin="5,0,0,0"
                        Orientation="Horizontal"
                        Canvas.Left="0">
                <TextBlock Name="tbk1"
                           Padding="0,0,10,0"
                           MinWidth="{Binding ElementName=brd,Path=ActualWidth}"
                           Text="A display of test text that is wider than the control."/>
                <TextBlock MinWidth="{Binding ElementName=brd,Path=ActualWidth}"
                           Text="{Binding ElementName=tbk1,Path=Text}"/>
            </StackPanel>
            <Canvas.Triggers>
                <EventTrigger RoutedEvent="MouseEnter">
                    <BeginStoryboard Name="scroll">
                        <Storyboard RepeatBehavior="Forever">
                            <DoubleAnimation To="{Binding ElementName=tbk1,Path=ActualWidth,Converter={StaticResource ChangeSignConverter}}" 
                                             Duration="0:0:4"  
                                             Storyboard.TargetName="spl1"
                                             Storyboard.TargetProperty="(Canvas.Left)" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger> 
                <EventTrigger RoutedEvent="MouseLeave">
                    <StopStoryboard BeginStoryboardName="scroll"/>
                </EventTrigger>
            </Canvas.Triggers>
        </Canvas>

转换器类:

class ChangeSignConverter : IValueConverter
{
  object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    return Convert.ToDouble(value) * -1;
  }

  object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    return Convert.ToDouble(value) * -1;
  }
}
于 2013-10-04T16:12:39.020 回答
1

您还可以使用 WPF动画功能。您创建一个自定义控件,其中包含一个 TextBlock。定义控件的宽度(这将小于文本块的宽度。然后定义情节提要和双重动画以根据需要对其进行动画处理(更慢/更快,仅向右动画,向右然后向左动画等等)。

这只是一个想法。我目前很着急,但如果您需要,我可以为您提供额外的代码。

于 2013-10-04T15:04:14.070 回答
0

我还会将 Timer 用于您描述的功能。如果您坚持在某个指定的时间间隔内更改 Label,我认为没有太多其他解决方案。另一方面,我可能会使用 ToolTip,我认为这更直观。

于 2013-10-04T15:01:32.377 回答