我有一个依赖属性双文,我想要完成的是每当我改变<的值时,用文本度旋转(用动画)一行strong>文字属性。
有没有比实现OnTextPropertyChanged更好的方法并处理动画?或者可以在XAML中完成?
这是一个演示代码:
MainWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:WpfApplication1" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="200" Width="200" x:Name="Root">
<Grid>
<TextBox Width="50" Height="20" VerticalAlignment="Top"
Text="{Binding Text, ElementName=Root, Mode=TwoWay}"/>
<Grid Width="100" Height="100" Background="Gray" x:Name="Grid">
<Line Grid.Row="1" X2="100" Y2="100" Stroke="Red"/>
</Grid>
</Grid>
</Window>
和MainWindow.xaml.cs(不使用):
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(double), typeof(MainWindow), new FrameworkPropertyMetadata(0.0));
public double Text
{
get { return (double)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public MainWindow()
{
InitializeComponent();
}
}
}
答案 0 :(得分:1)
这可以通过Binding来实现:
<TextBox Width="50" Height="20" VerticalAlignment="Top"
Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Grid Width="100" Height="100" Background="Gray" x:Name="Grid">
<Line Grid.Row="1" X2="100" Y2="100" Stroke="Red">
<Line.RenderTransform>
<RotateTransform CenterX="50" CenterY="50" Angle="{Binding Path=Text, Mode=OneWay, Converter={StaticResource ResourceKey=SToD}}"/>
</Line.RenderTransform>
</Line>
</Grid>
您的转换器只需将您的字符串转换为双return System.Convert(value.ToString());
。
我在测试时发现的一个很酷的功能是,如果你没有在TextBox中输入double值,会自动添加验证规则,返回ValidationError。
要完成这项工作,您必须使用this.DataContext = this;
将MainWindows DataContext连接到自身。
编辑: 我写了一个小助手类,它为你做动画:
public class DoubleAnimationManager
{
private static Dictionary<DependencyObject, AnimationHelper> _helperDic = new Dictionary<DependencyObject, AnimationHelper>();
public static PropertyPath GetProperty(DependencyObject obj)
{
return (PropertyPath)obj.GetValue(PropertyProperty);
}
public static void SetProperty(DependencyObject obj, PropertyPath value)
{
obj.SetValue(PropertyProperty, value);
}
public static readonly DependencyProperty PropertyProperty = DependencyProperty.RegisterAttached(
"Property",
typeof(PropertyPath),
typeof(DoubleAnimationManager),
new PropertyMetadata(
(o, e) =>
{
if (!_helperDic.ContainsKey(o))
_helperDic[o] = new AnimationHelper(o);
_helperDic[o].Path = (PropertyPath)e.NewValue;
}));
public static int GetDelayTimeInMS(DependencyObject obj)
{
return (int)obj.GetValue(DelayTimeInMSProperty);
}
public static void SetDelayTimeInMS(DependencyObject obj, int value)
{
obj.SetValue(DelayTimeInMSProperty, value);
}
public static readonly DependencyProperty DelayTimeInMSProperty = DependencyProperty.RegisterAttached(
"DelayTimeInMS",
typeof(int),
typeof(DoubleAnimationManager),
new PropertyMetadata(0,
(o, e) =>
{
if (!_helperDic.ContainsKey(o))
_helperDic[o] = new AnimationHelper(o);
_helperDic[o].DelayInMS = (int)e.NewValue;
}));
public static double GetValue(DependencyObject obj)
{
return (double)obj.GetValue(ValueProperty);
}
public static void SetValue(DependencyObject obj, double value)
{
obj.SetValue(ValueProperty, value);
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached(
"Value",
typeof(double),
typeof(DoubleAnimationManager),
new PropertyMetadata(
(o, e) =>
{
if (!_helperDic.ContainsKey(o))
_helperDic[o] = new AnimationHelper(o);
_helperDic[o].ToValue = (double)e.NewValue;
if (!_helperDic[o].Started)
{
_helperDic[o].FromValue = (double)e.OldValue;
_helperDic[o].Start();
}
}));
}
public class AnimationHelper
{
private bool _remMode;
private DependencyObject _target;
private BackgroundWorker _bw = new BackgroundWorker();
public double FromValue { get; set; }
private double _toValue;
public double ToValue
{
get { return _toValue; }
set
{
if (Started)
{
_remMode = true;
}
_toValue = value;
}
}
public bool Started { get; private set; }
private int _delayInMS;
public int DelayInMS
{
get { return _delayInMS; }
set
{
_delayInMS = value;
}
}
public PropertyPath Path { get; set; }
public AnimationHelper(DependencyObject target)
{
_target = target;
_bw.DoWork += delegate
{
System.Threading.Thread.Sleep(DelayInMS);
};
_bw.RunWorkerCompleted += delegate
{
StartAnimation();
};
}
private Storyboard GetStoryboard()
{
Storyboard sb = new Storyboard();
DoubleAnimation da = new DoubleAnimation(ToValue, new TimeSpan(0, 0, 3));
da.From = FromValue;
Storyboard.SetTarget(da, _target);
Storyboard.SetTargetProperty(da, Path);
sb.Children.Add(da);
sb.Completed += delegate
{
if (_remMode)
{
StartAnimation();
_remMode = false;
}
else
{
Started = false;
}
};
return sb;
}
private void StartAnimation()
{
GetStoryboard().Begin();
FromValue = ToValue;
}
public void Start()
{
Started = true;
_bw.RunWorkerAsync();
}
}
如何使用它:
<TextBox Width="50" Height="20" VerticalAlignment="Top"
Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Grid Width="100" Height="100" Background="Gray" x:Name="Grid">
<Line Grid.Row="1" X2="100" Y2="100" Stroke="Red" local:DoubleAnimationManager.Property="(UIElement.RenderTransform).(RotateTransform.Angle)" local:DoubleAnimationManager.Value="{Binding Path=Text, Mode=OneWay, Converter={StaticResource ResourceKey=SToD}}">
<Line.RenderTransform>
<RotateTransform CenterX="50" CenterY="50"/>
</Line.RenderTransform>
</Line>
</Grid>