【发布时间】:2020-03-25 23:16:43
【问题描述】:
我正在尝试在名为 MarkerImage 的自定义 WPF UserControl 中更新图像的旋转角度。我在 MarkerImage 上有一个名为 Heading 的属性,当它发生变化时,我希望图像的角度发生变化。我尝试了很多方法,它们都正确设置了初始角度,但没有一个能够更新角度。这是控件的 XAML:
以下是我尝试过的一些方法:
1) 在 MarkerImage 上创建了一个名为 Heading 的依赖属性。
public static readonly DependencyProperty HeadingProperty = DependencyProperty.Register("Heading", typeof(uint), typeof(MarkerImage), new PropertyMetadata(default(uint)));
然后我将 MarkerImage 的 DataContext 设置为 {RelativeSource Self} 并将 RotateTransform 的 Angle 属性绑定到该 Heading 属性:
<UserControl x:Class="Pilot2ATC_EFB.Map.MarkerImage"
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:Pilot2ATC_EFB.Map"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DesignHeight="450" d:DesignWidth="800" Width="35" Height="35" x:Name="ctlMarkerImage">
<Image x:Name="userImage" HorizontalAlignment="Center" Height="34" Width="34" RenderTransformOrigin="0.5,0.5" Source="/myApplication;component/Resources/arrow.png" Margin="0,0,0,0" VerticalAlignment="Center">
<Image.RenderTransform>
<RotateTransform x:Name="rotateTransform" Angle="{Binding Path=Heading, UpdateSourceTrigger=PropertyChanged}"/>
</Image.RenderTransform>
</Image>
这会在创建控件并设置标题属性时正确设置角度。但是,随着 Heading 属性在 Heading 属性的 Set{} 中更新:
SetValue(HeadingProperty, value % 360);
图像角度不变。
2)尝试直接从属性Heading Set代码设置Angle属性:
_Heading = value % 360;
rotateTransform.Angle = _Heading;
这再次设置了初始角度,但在标题更新时没有改变图像的旋转。
3) 每次 Heading 改变时都尝试用一个新的 RotateTransform 替换:
userImage.RenderTransform = new RotateTransform(_Heading);
这也可以设置初始角度,但是当 Heading 值随后发生变化时什么也没做。
4) 尝试在 Heading 更改时对 Angle 属性进行动画处理。 (rotateTransform 是 RotateTransform 元素的 x:Name):
var rotAnimation = new DoubleAnimation(Heading, TimeSpan.FromMilliseconds(1));
rotateTransform.BeginAnimation(RotateTransform.AngleProperty, rotAnimation);
再一次,初始值设置正确,但更新无效。
这是使用 DependencyProperty 时设置 Heading 属性的代码。
public double Heading
{
get { return (double)GetValue(HeadingProperty); }
set
{
if (value < 0)
value = 360;
SetValue(HeadingProperty, value % 360);
}
}
当然,我确认代码正在执行,初始设置后航向值发生变化,但图像没有被旋转。
我在论坛中尝试了这些和其他建议的 10 多个其他变体,但它们要么抛出错误,要么没有设置初始值,要么与这 4 个结果相同。
似乎有一种确定的方法可以从后面的代码或通过绑定动态更改 WPF UserControl 中图像的旋转角度,但我不知道那会是什么。任何帮助将不胜感激。
【问题讨论】:
-
不完全确定,但可能存在一个问题。
DataContext是由托管您的MarkerImage的Window设置的吗?这可能会在设置初始值后停止绑定。要进行测试,请尝试删除DataContext="{Binding RelativeSource={RelativeSource Self}}"并将DataContext="{Binding RelativeSource={AncestorType local:MarkerImage}}"添加到根元素(在您的情况下为Image)。 -
首先,UserControl 不应该显式设置它自己的DataContext。这样做会破坏通常的 DataContext 绑定,例如
Heading="{Binding Something}"将不再起作用。与 UserControl 自身属性的绑定应类似于Angle="{Binding Heading, RelativeSource={AncestorType=UserControl}},没有 UpdateSourceTrigger,这在 OneWay 绑定中无效。 -
那么属性的类型应该是
double,而不是uint。除此之外,在您向我们展示您实际尝试设置 Heading 属性的代码之前,我们无法回答您的问题。如果那是一个 Binding,由于上述原因,它可能无法正常工作。 -
感谢两位的建议。我添加了用于将 Heading DependencyProperty 值设置到问题的代码。我还尝试了您关于设置 DataContext 和 Binding 值的两个建议,以及两者的几种变体。他们的初始设置工作结果相同,但更新不起作用。就好像 RotateTransform 的角度无法更改......这就是促使方法 #3 替换它而不是尝试更改它的原因。但这也没有用。
-
嗯,你绝对可以改变旋转变换的角度(我只是自己测试过)。如果没有可重复的例子,我想的不多。旁注:您对
Heading的逻辑和验证不应该放在setter 中,而应该放在validation and/or coercion callbacks 中。这是因为如果通过绑定更新属性(WPF 绑定系统直接调用SetValue),则不会调用该setter。
标签: c# wpf animation data-binding rotatetransform