C# 为什么绑定不';你不能用动画吗?
我有一个动画绑定属性的简单问题。下面是一个简单的例子来说明这一点: 视图模型:C# 为什么绑定不';你不能用动画吗?,c#,.net,wpf,animation,binding,C#,.net,Wpf,Animation,Binding,我有一个动画绑定属性的简单问题。下面是一个简单的例子来说明这一点: 视图模型: public class ViewModel { private double myProperty; public double MyProperty { get { return myProperty; } set { myProperty = value; /* Break point here */ } } public ViewM
public class ViewModel
{
private double myProperty;
public double MyProperty
{
get { return myProperty; }
set { myProperty = value; /* Break point here */ }
}
public ViewModel()
{
MyProperty = 20;
}
}
public class MyControl : Button
{
protected override void OnClick()
{
base.OnClick();
Height = ActualHeight + 20;
}
}
public class MyAnimatedControl : Button
{
protected override void OnClick()
{
base.OnClick();
DoubleAnimation a = new DoubleAnimation(ActualHeight + 20, new Duration(TimeSpan.FromMilliseconds(500)));
this.BeginAnimation(HeightProperty, a);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}
}
<Grid>
<StackPanel>
<local:MyAnimatedControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Animated"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 1"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 2"/>
</StackPanel>
</Grid>
MyControl:
public class ViewModel
{
private double myProperty;
public double MyProperty
{
get { return myProperty; }
set { myProperty = value; /* Break point here */ }
}
public ViewModel()
{
MyProperty = 20;
}
}
public class MyControl : Button
{
protected override void OnClick()
{
base.OnClick();
Height = ActualHeight + 20;
}
}
public class MyAnimatedControl : Button
{
protected override void OnClick()
{
base.OnClick();
DoubleAnimation a = new DoubleAnimation(ActualHeight + 20, new Duration(TimeSpan.FromMilliseconds(500)));
this.BeginAnimation(HeightProperty, a);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}
}
<Grid>
<StackPanel>
<local:MyAnimatedControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Animated"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 1"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 2"/>
</StackPanel>
</Grid>
MyAnimatedControl:
public class ViewModel
{
private double myProperty;
public double MyProperty
{
get { return myProperty; }
set { myProperty = value; /* Break point here */ }
}
public ViewModel()
{
MyProperty = 20;
}
}
public class MyControl : Button
{
protected override void OnClick()
{
base.OnClick();
Height = ActualHeight + 20;
}
}
public class MyAnimatedControl : Button
{
protected override void OnClick()
{
base.OnClick();
DoubleAnimation a = new DoubleAnimation(ActualHeight + 20, new Duration(TimeSpan.FromMilliseconds(500)));
this.BeginAnimation(HeightProperty, a);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}
}
<Grid>
<StackPanel>
<local:MyAnimatedControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Animated"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 1"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 2"/>
</StackPanel>
</Grid>
主窗口:
public class ViewModel
{
private double myProperty;
public double MyProperty
{
get { return myProperty; }
set { myProperty = value; /* Break point here */ }
}
public ViewModel()
{
MyProperty = 20;
}
}
public class MyControl : Button
{
protected override void OnClick()
{
base.OnClick();
Height = ActualHeight + 20;
}
}
public class MyAnimatedControl : Button
{
protected override void OnClick()
{
base.OnClick();
DoubleAnimation a = new DoubleAnimation(ActualHeight + 20, new Duration(TimeSpan.FromMilliseconds(500)));
this.BeginAnimation(HeightProperty, a);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}
}
<Grid>
<StackPanel>
<local:MyAnimatedControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Animated"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 1"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 2"/>
</StackPanel>
</Grid>
公共部分类主窗口:窗口
{
公共主窗口()
{
DataContext=新的ViewModel();
初始化组件();
}
}
我继承了两个控件(MyControl和MyAnimatedControl),它们的高度属性绑定到ViewModel中的MyProperty属性(模式双向)
单击控件时,它们会增加其高度属性。MyControl为其指定一个新值,MyAnimatedControl为其设置动画
问题:
public class ViewModel
{
private double myProperty;
public double MyProperty
{
get { return myProperty; }
set { myProperty = value; /* Break point here */ }
}
public ViewModel()
{
MyProperty = 20;
}
}
public class MyControl : Button
{
protected override void OnClick()
{
base.OnClick();
Height = ActualHeight + 20;
}
}
public class MyAnimatedControl : Button
{
protected override void OnClick()
{
base.OnClick();
DoubleAnimation a = new DoubleAnimation(ActualHeight + 20, new Duration(TimeSpan.FromMilliseconds(500)));
this.BeginAnimation(HeightProperty, a);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}
}
<Grid>
<StackPanel>
<local:MyAnimatedControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Animated"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 1"/>
<local:MyControl Height="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Normal 2"/>
</StackPanel>
</Grid>
当我单击其中一个MyControl时,绑定工作正常,所有控件的高度都会更新,断点在ViewModel中工作。但当我单击MyAnimatedControl时,绑定似乎不再工作:它单独增长,绑定不再工作,而两个正常控件仍然一起增长。它不再与其他控件共享相同的高度
是否有一种方法可以对动画依赖项属性进行操作绑定,从而在整个动画过程中更新ViewModel?我读了,但它没有回答
谢谢。控件.Height属性是一个
dependencProperty
属性,并且dependencProperty
可以从多种来源进行设置,例如样式设置器
、动画
、源代码等。因此,微软必须定义一个优先顺序,以决定哪些更改dependencProperty
值的可能方法比其他方法更重要
从逻辑上讲,正如您在示例中所做的那样,从动画中设置dependencProperty
,应该“覆盖”从其他来源(例如从属性设置器)设置的值。有关dependencProperty
值优先级列表的完整信息,请参阅MSDN上的页面
然而,使用您的代码,我无法重现您的问题。我可以反复点击每一个按钮
,看到它的尺寸不断增大。因此,如果你不能做到这一点,那么我怀疑你有其他一些代码干扰了这一点。如果这不是你的问题,那么请清楚地解释是什么问题
更新>>>
哦,我想我知道你现在想要什么了。。。您想知道为什么在动画
设置属性值动画时不调用属性设置器。但是,这不起作用,因为动画
不会永久更改属性值。从页面的“数据绑定和动画制作”部分:
大多数动画属性可以是数据绑定或动画;例如,可以设置双重动画
的持续时间
属性的动画。但是,由于计时系统的工作方式,数据绑定或动画的行为与其他数据绑定或动画对象不同
问题似乎是动画属性同时也是绑定的源。为了解决这个问题,您可以创建另一个height属性(例如,MyHeight
),该属性在控件的高度更改时更新,并作为OneWayToSource
绑定的目标
public class MyAnimatedControl : Button
{
public static readonly DependencyProperty MyHeightProperty =
DependencyProperty.Register(
"MyHeight", typeof(double), typeof(MyAnimatedControl));
public double MyHeight
{
get { return (double)GetValue(MyHeightProperty); }
set { SetValue(MyHeightProperty, value); }
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
MyHeight = sizeInfo.NewSize.Height;
}
}
约束力:
<local:MyAnimatedControl ...
MyHeight="{Binding MyProperty, Mode=OneWayToSource}"
Height="{Binding MyProperty, Mode=OneWay}"/>
最后,正如Rohit Vats在他的回答中所写的,您需要在已完成的事件处理程序中移除Height属性上的动画保留:
protected override void OnClick()
{
base.OnClick();
DoubleAnimation a = new DoubleAnimation(ActualHeight + 20,
new Duration(TimeSpan.FromMilliseconds(500)));
a.Completed += (s, e) =>
{
BeginAnimation(Button.HeightProperty, null); // Remove animation.
SetCurrentValue(Button.HeightProperty, ActualHeight); // Set value.
};
this.BeginAnimation(Button.HeightProperty, a);
}
问题是动画具有更高的优先顺序,所以当它应用于任何属性时,该属性中的后续更改不会反映在UI和绑定中
如上所述,您可以通过三种方法解决此问题:
将动画的FillBehavior设置为“停止”
移除整个故事板
从单个属性中删除动画
在您的情况下,我们可以使用第三个选项在动画完成后从高度DP中删除动画
其次,您应该调用方法来设置DP,它将更新绑定,从而更新绑定的ViewModel属性
将所有这些内容放入双动画的
事件中:
public class MyAnimatedControl : Button
{
protected override void OnClick()
{
base.OnClick();
DoubleAnimation a = new DoubleAnimation(ActualHeight + 20,
new Duration(TimeSpan.FromMilliseconds(500)));
a.Completed += (s, e) =>
{
BeginAnimation(Button.HeightProperty, null); // Remove animation.
SetCurrentValue(Button.HeightProperty, ActualHeight); // Set value.
};
this.BeginAnimation(Button.HeightProperty, a);
}
}
还要确保您的ViewModel正在实现,并且属性更改事件是从MyProperty
setter引发的。单击animatedcontrol时会发生什么?它能用一次吗?实际高度的值是多少?如果只单击普通控件,主窗口中的所有3个控件都会更新,并且都会增长。当您单击动画控件时,它会单独增长,绑定不再工作,而两个普通控件仍会一起增长。感谢这些有用的信息。是的,我一定不是很清楚。它们确实在每次单击时都会增长,但动画控件的高度(包含在ViewModel中)与两个普通控件的高度不同。@Max.您是说:a.FillBehavior=FillBehavior.HoldEnd@Core One我知道thos属性,但它对我解决这个问题没有帮助。@Sheridan+1是的,谢谢你的编辑,我认为我的问题来自于此。+1你的解决方案很好,但不适用于双向模式。不管怎样,这条线索很好。至少对我来说,它对双向也很有效。您是如何尝试的?如果您只是将单向ToSource模式替换为双向模式,则不会更改代码的行为(即,如果ViewModel的my属性已更新,则不会更改MyAnimatedControl的Height属性),您仍然会将Height
属性单向绑定到视图模型(请参见我的编辑)。但是,如果由于以下原因而忽略VM属性,则返回初始值: