今天我正在處理為在模板中創建的組件創建影片的問題。
以前我有這樣的事情(在 TextBlock onl oad 觸發器中實作):
<TextBlock.Triggers>
<EventTrigger RoutedEvent="TextBlock.Loaded">
<BeginStoryboard>
<Storyboard
x:Name="contentStoryboard"
Storyboard.TargetName="contentText">
<DoubleAnimation
BeginTime="0:0:0"
Storyboard.TargetProperty="(Canvas.Left)"
AutoReverse="{Binding MarqueeBouncing, RelativeSource={RelativeSource AncestorType={x:Type local:MarqueeTextBlockEx}}}"
Duration="{Binding MarqueeDuration, RelativeSource={RelativeSource AncestorType={x:Type local:MarqueeTextBlockEx}}}"
RepeatBehavior="Forever">
<DoubleAnimation.From>
<MultiBinding Converter="{StaticResource StartPositionConverter}">
<Binding Path="MarqueeStartPosition" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MarqueeTextBlockEx}}"/>
<Binding ElementName="border" Path="ActualWidth"/>
<Binding ElementName="contentText" Path="ActualWidth"/>
<Binding Path="WaitForText" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MarqueeTextBlockEx}}"/>
</MultiBinding>
</DoubleAnimation.From>
<DoubleAnimation.To>
<MultiBinding Converter="{StaticResource EndPositionConverter}">
<Binding Path="MarqueeEndPosition" RelativeSource="{RelativeSource AncestorType={x:Type local:MarqueeTextBlockEx}}"/>
<Binding ElementName="border" Path="ActualWidth"/>
<Binding ElementName="contentText" Path="ActualWidth"/>
<Binding Path="WaitForText" RelativeSource="{RelativeSource AncestorType={x:Type local:MarqueeTextBlockEx}}"/>
</MultiBinding>
</DoubleAnimation.To>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
在我想實作 bool 引數來控制影片的開啟和關閉之后。我在后面創建了一個代碼:
public MarqueeTextBlockEx()
{
Loaded = onl oaded;
}
static MarqueeTextBlockEx()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MarqueeTextBlockEx),
new FrameworkPropertyMetadata(typeof(MarqueeTextBlockEx)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
contentBorder = GetBorder("border");
contentCanvas = GetCanvas("contentCanvas");
contentTextBlock = GetTextBlock("contentText");
}
protected TextBlock GetTextBlock(string textBlockName)
{
return this.Template.FindName(textBlockName, this) as TextBlock;
}
protected virtual void OnLoaded(object sender, RoutedEventArgs e)
{
Storyboard = CreateStoryboard();
if (MarqueeEnabled)
Storyboard.Begin();
}
private Storyboard CreateStoryboard()
{
var storyboard = new Storyboard();
var doubleAnimation = new DoubleAnimation()
{
AutoReverse = MarqueeBouncing,
BeginTime = new TimeSpan(0, 0, 0),
Duration = MarqueeDuration,
RepeatBehavior = RepeatBehavior.Forever,
From = GetStartPosition(),
To = GetEndPosition()
};
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("Canvas.Left"));
Storyboard.SetTarget(doubleAnimation, contentTextBlock);
return storyboard;
}
private double GetStartPosition()
{
var startPosition = MarqueeStartPosition;
var canvasWidth = contentBorder.ActualWidth;
var textWidth = contentTextBlock.ActualWidth;
var waitForText = WaitForText;
switch (MarqueeStartPosition)
{
case MarqueeTextAnimationPlace.LeftOutside:
return -textWidth;
case MarqueeTextAnimationPlace.LeftInside:
return waitForText && IsTextTooLong(canvasWidth, textWidth)
? -(textWidth - canvasWidth)
: 0;
case MarqueeTextAnimationPlace.RightInside:
return waitForText && IsTextTooLong(canvasWidth, textWidth)
? 0
: canvasWidth - textWidth;
case MarqueeTextAnimationPlace.RightOutside:
default:
return canvasWidth;
}
}
private double GetEndPosition()
{
var startPosition = MarqueeEndPosition;
var canvasWidth = contentBorder.ActualWidth;
var textWidth = contentTextBlock.ActualWidth;
var waitForText = WaitForText;
switch (startPosition)
{
case MarqueeTextAnimationPlace.LeftOutside:
return -textWidth;
case MarqueeTextAnimationPlace.LeftInside:
return waitForText && IsTextTooLong(canvasWidth, textWidth)
? -(textWidth - canvasWidth)
: 0;
case MarqueeTextAnimationPlace.RightInside:
return waitForText && IsTextTooLong(canvasWidth, textWidth)
? 0
: canvasWidth - textWidth;
case MarqueeTextAnimationPlace.RightOutside:
default:
return canvasWidth;
}
}
// And of course the property for control:
public bool MarqueeEnabled
{
get => marqueeEnabled;
set
{
marqueeEnabled = value;
if (Storyboard != null)
{
if (value)
Storyboard.Begin();
else
{
Storyboard.Stop();
TextPosition = 0;
}
}
}
}
TextBlock 組件就是這樣設定的
<Border
x:Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid
x:Name="grid"
Margin="{TemplateBinding Padding}">
<Canvas
x:Name="contentCanvas"
ClipToBounds="True"
Height="{Binding ActualHeight, ElementName=contentText}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Width="{Binding ActualWidth, ElementName=grid}">
<TextBlock
x:Name="contentText"
Canvas.Left="{Binding TextPosition, RelativeSource={RelativeSource AncestorType={x:Type local:MarqueeTextBlockEx}}}"
Foreground="{TemplateBinding Foreground}"
Height="Auto"
HorizontalAlignment="Left"
Text="{TemplateBinding Text}"
VerticalAlignment="Center"
Width="Auto"/>
</Canvas>
</Grid>
</Border>
是什么導致它不能那樣作業?
uj5u.com熱心網友回復:
添加DoubleAnimation到 的Children屬性Storyboard并在 周圍添加括號Canvas.Left:
var storyboard = new Storyboard();
var doubleAnimation = new DoubleAnimation()
{
...
};
storyboard.Children.Add(doubleAnimation);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Left)"));
Storyboard.SetTarget(doubleAnimation, contentTextBlock);
storyboard.Begin();
如果您仍然無法使用它,請編輯您的問題以包含一個最小且可重復的示例。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/524079.html
標籤:C#wpfxml故事板
