WPF绑定Canvas.LeftCanvas.Top到Point DependencyProperty,使用PointAnimation

WPF绑定Canvas.LeftCanvas.Top到Point DependencyProperty,使用PointAnimation,第1张

概述WPF绑定Canvas.Left / Canvas.Top到Point DependencyProperty,使用PointAnimation

请考虑以下简化的例子来说明我的问题:

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WIDth="500" Height="500" title="Click anywhere to animate the movement of the blue thingy..."> <Canvas x:name="canvas" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="AntiqueWhite" MouseDown="canvas_MouseDown" /> </Window>

MainWindow.xaml.cs

using System; using System.windows; using System.windows.input; using System.windows.Media.Animation; namespace WpfApplication1 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.canvas.Children.Add(new Thingy()); } private voID canvas_MouseDown(object sender,MousebuttonEventArgs e) { var thingy = (Thingy)this.canvas.Children[0]; var from = new Point(0.0,0.0); var to = new Point( canvas.ActualWIDth - thingy.ActualWIDth,canvas.ActualHeight - thingy.ActualHeight ); var locAnim = new PointAnimation( from,to,new Duration(TimeSpan.FromSeconds(5)) ); locAnim.Completed += (s,a) => { // Only at this line does the thingy move to the // correct position... thingy.Location = to; }; thingy.Location = from; thingy.BeginAnimation(Thingy.LocationProperty,locAnim); } } }

Thingy.xaml

添加应用程序清单以确保在windows XP,Vista和7上提升权限的可靠程度如何?

C#窗体不呈现控件

stringinput从文本框if / else

我有什么select使用C#在windows Server上添加和删除IPSec策略?

如果外部命令的输出是废话,最好抛出exception?

<UserControl x:Class="WpfApplication1.Thingy" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WIDth="50" Height="50" Background="Blue" />

Thingy.xaml.cs

using System.windows; using System.windows.Controls; using System.windows.Data; namespace WpfApplication1 { public partial class Thingy : UserControl { public static DependencyProperty LocationProperty = DependencyProperty.Register( "Location",typeof(Point),typeof(Thingy) ); public Thingy() { InitializeComponent(); Canvas.Setleft(this,0.0); Canvas.Settop(this,0.0); var xBind = new Binding(); xBind.source = this; xBind.Path = new PropertyPath(Canvas.leftProperty); xBind.Mode = BindingMode.TwoWay; var yBind = new Binding(); yBind.source = this; yBind.Path = new PropertyPath(Canvas.topProperty); yBind.Mode = BindingMode.TwoWay; var locBind = new MultiBinding(); locBind.Converter = new PointConverter(); locBind.Mode = BindingMode.TwoWay; locBind.Bindings.Add(xBind); locBind.Bindings.Add(yBind); BindingOperations.SetBinding( this,Thingy.LocationProperty,locBind ); } public Point Location { get { return (Point)this.GetValue(LocationProperty); } set { this.SetValue(LocationProperty,value); } } } }

PointConverter.cs

using System; using System.Globalization; using System.windows; using System.windows.Data; namespace WpfApplication1 { public class PointConverter : IMultiValueConverter { public object Convert(object[] v,Type t,object p,CultureInfo c) { return new Point((double)v[0],(double)v[1]); } public object[] ConvertBack(object v,Type[] t,CultureInfo c) { return new object[] { ((Point)v).X,((Point)v).Y }; } } }

这里的目标是:

使用LocationProperty来 *** 作和访问Canvas.leftProperty和Canvas.topProperty值。

用PointAnimation类animation说LocationProperty 。

目标1似乎工作正常,只有在试图animation化LocationProperty ,它不会像预期的那样运行。

“预期”是指Thingy的实例应该随着animation的进展而移动。

我能够使用DoubleAnimation类的两个实例来完成此 *** 作。

如果问题是Point是一个值types,那么我怀疑我可以定义我自己的Pointtypes和我自己的AnimationTimeline 。 这不是我想要做的。 这是一个更大的项目的一部分, LocationProperty将用于其他事情。

说实话,底线是,在我看来,这应该只是工作,你能告诉我:

为什么不呢?

如果有解决问题的定义?

我还会提到,我针对这个项目的.Net Framework 4.5。

谢谢。

从所有当前暂停的线程获取堆栈跟踪信息(托pipe)

windows Azure支持除.NET以外的其他技术

windows句柄如果控件设置为可见= false(.NET)

尝试安装windows服务时,InstallUtil.exe被删除

微软打破了.NET兼容性?

这是最简单的代码来动画的东西。

它利用依赖属性回调

不使用绑定

不使用转换器

不使用故事板

主窗口:

using System; using System.windows; using System.windows.Controls; using System.windows.input; using System.windows.Media.Animation; namespace WpfApplication1 { public partial class MainWindow { public MainWindow() { InitializeComponent(); } private voID MainWindow_OnMouseDown(object sender,MousebuttonEventArgs e) { var x = Canvas.Getleft(Control1); var y = Canvas.Gettop(Control1); x = double.IsNaN(x) ? 0 : x; y = double.IsNaN(y) ? 0 : y; var point1 = new Point(x,y); var point2 = e.Getposition(this); var animation = new PointAnimation(point1,point2,new Duration(TimeSpan.FromSeconds(1))); animation.EasingFunction = new CubicEase(); Control1.BeginAnimation(UserControl1.LocationProperty,animation); } } }

主窗口:

<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/Expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication1" mc:Ignorable="d" title="MainWindow" Height="350" WIDth="525" MouseDown="MainWindow_OnMouseDown"> <Canvas> <local:UserControl1 Background="Red" Height="100" WIDth="100" x:name="Control1" /> </Canvas> </Window>

控制:

using System.windows; using System.windows.Controls; namespace WpfApplication1 { public partial class UserControl1 { public static Readonly DependencyProperty LocationProperty = DependencyProperty.Register( "Location",typeof(UserControl1),new UIPropertyMetadata(default(Point),OnLocationChanged)); public UserControl1() { InitializeComponent(); } public Point Location { get { return (Point) GetValue(LocationProperty); } set { SetValue(LocationProperty,value); } } private static voID OnLocationChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) { var control1 = (UserControl1) d; var value = (Point) e.NewValue; Canvas.Setleft(control1,value.X); Canvas.Settop(control1,value.Y); } } }

控制:

<UserControl x:Class="WpfApplication1.UserControl1" 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:WpfApplication1" mc:Ignorable="d" d:DesignHeight="300" d:DesignWIDth="300"> </UserControl>

Todo:根据您的需要调整代码:)

编辑:一个简单的双向绑定,听Canvas.[left|top]Property :

(待加强)

using System; using System.ComponentModel; using System.windows; using System.windows.Controls; namespace WpfApplication1 { public partial class UserControl1 { public static Readonly DependencyProperty LocationProperty = DependencyProperty.Register( "Location",new PropertyMetadata(default(Point),OnLocationChanged)); public UserControl1() { InitializeComponent(); DependencyPropertyDescriptor.FromProperty(Canvas.leftProperty,typeof(Canvas)) .AddValueChanged(this,OnleftChanged); DependencyPropertyDescriptor.FromProperty(Canvas.topProperty,OntopChanged); } public Point Location { get { return (Point) GetValue(LocationProperty); } set { SetValue(LocationProperty,value); } } private voID OnleftChanged(object sender,EventArgs eventArgs) { var left = Canvas.Getleft(this); Location = new Point(left,Location.Y); } private voID OntopChanged(object sender,EventArgs e) { var top = Canvas.Gettop(this); Location = new Point(Location.X,top); } private static voID OnLocationChanged(DependencyObject d,value.Y); } } }

我喜欢Aybe的答案,但它没有解释为什么原始代码不起作用。 我运行你的代码,并尝试了一些替代方法,看来发生了什么事是绑定转换器在动画过程中被忽略。 如果您在转换器方法中设置断点,或者执行DeBUG.Writeline,则无论哪种方式,您都可以看到转换器不会在整个动画中被调用,而只是在您的代码中明确设置属性时。

深入挖掘,问题在于您设置Thingy绑定的方式。 绑定源属性应该是Thingy.Location而目标属性应该是Canvas.left和Canvas.top 。 你有倒退 – 你正在使Canvas.left和Canvas.top源属性和Thingy.Location目标属性。 您可能会认为将其设置为双向绑定可以使其工作(并且在您明确设置Thingy.Location属性时),但是看起来双向绑定方面在动画中将被忽略。

一个解决方案是不要在这里使用多重绑定。 当多个属性被多个属性或条件所取代时,多重绑定是真正的。 在这里,你有多个属性( Canvas.left和Canvas.top ),你想用一个属性来源 – Thingy.Location 。 所以,在Thingy构造函数中:

var xBind = new Binding(); xBind.source = this; xBind.Path = new PropertyPath(Thingy.LocationProperty); xBind.Mode = BindingMode.OneWay; xBind.Converter = new PointTodoubleConverter(); xBind.ConverterParameter = false; BindingOperations.SetBinding(this,Canvas.leftProperty,xBind); var yBind = new Binding(); yBind.source = this; yBind.Path = new PropertyPath(Thingy.LocationProperty); yBind.Mode = BindingMode.OneWay; yBind.Converter = new PointTodoubleConverter(); yBind.ConverterParameter = true; BindingOperations.SetBinding(this,Canvas.topProperty,yBind);

另一个区别是绑定转换器。 而不是采取两个doubles ,给你一个Point ,我们需要一个转换器,需要一个Point并提取用于Canvas.left和Canvas.top属性(我使用ConverterParameter指定哪一个是所需的)的双。 所以:

public class PointTodoubleConverter : IValueConverter { public object Convert(object value,Type targettype,object parameter,CultureInfo culture) { var pt = (Point)value; bool isY = (bool)parameter; return isY ? pt.Y : pt.X; } public object ConvertBack(object value,CultureInfo culture) { return value; } }

这使得动画工作,同时仍然使用绑定和转换器。 唯一的缺点是Canvas属性和Thingy.Location之间的绑定必须是单向的,因为没有办法将Canvas.left或Canvas.top单独转换回完整的Point 。 换句话说,如果您随后更改Canvas.left或Canvas.top , Thingy.Location将不会更新。 (这当然也适用于任何无约束的解决方案)。

但是,如果你回到原来的多重绑定版本,只需将代码添加到Location属性更改处理程序来更新Canvas.left和Canvas.top ,就可以拥有你的蛋糕并且可以吃掉它。 他们不需要在这一点上是TwoWay绑定,因为你正在更新Location的属性更改处理程序中的Canvas.left和Canvas.top 。 基本上所有的实际绑定然后是确保Canvas.left和Canvas.top做的Location更新。

无论如何,这个谜还是解决了为什么你原来的方法不起作用。 设置复杂绑定时,正确识别源和目标是至关重要的。 TwoWay绑定并不是所有情况下的全部,特别是动画。

总结

以上是内存溢出为你收集整理的WPF绑定Canvas.Left / Canvas.Top到Point DependencyProperty,使用PointAnimation全部内容,希望文章能够帮你解决WPF绑定Canvas.Left / Canvas.Top到Point DependencyProperty,使用PointAnimation所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1276951.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存