我有一个 MyBool 类的实例,其属性为 IsTrue ,存储为 StaticResource 。我还有一个CheckBox,其IsChecked属性绑定到类的实例。
{Binding IsTrue, Mode=TwoWay, Source={StaticResource MyBoolInstance}}
工作正常。如果我在CheckBox上更改check属性, MyBool 的实例也会更新,反之亦然。
但是,如果我操纵CheckBox 的IsChecked属性一个StoryBoard
<Storyboard x:Key="ColourToggle">
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="IsChecked"
Storyboard.TargetName="ThisCheckBox">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>True</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
MyBool 实例的 IsTrue 属性不会更新!
有任何建议或解决方法吗?
答案 0 :(得分:3)
以下是完全重现问题的示例:
<StackPanel>
<StackPanel.Resources>
<l:MyBool x:Key="MyBool" IsTrue="False" />
</StackPanel.Resources>
<CheckBox x:Name="myCheckBox"
Content="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsChecked}"
IsChecked="{Binding Source={StaticResource MyBool}, Path=IsTrue, Mode=TwoWay}"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<CheckBox.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<BeginStoryboard x:Name="isCheckedBeginStoryboard">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsChecked">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>True</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeave">
<StopStoryboard BeginStoryboardName="isCheckedBeginStoryboard" />
</EventTrigger>
</CheckBox.Triggers>
</CheckBox>
<CheckBox Content="Also two way binding to MyBool.IsTrue no animation" IsChecked="{Binding Source={StaticResource MyBool}, Path=IsTrue}" />
<TextBlock Text="{Binding Source={StaticResource MyBool}, Path=IsTrue, StringFormat={}MyBool.IsTrue: {0}}" />
<TextBlock Text="{Binding ElementName=myCheckBox, Path=IsChecked, StringFormat={}myCheckBox.IsChecked: {0}}" />
</StackPanel>
MyBool
是一个同样实现INotifyPropertyChanged
的简单类:
public class MyBool : INotifyPropertyChanged
{
private bool _isTrue;
public bool IsTrue
{
get { return _isTrue; }
set
{
if (_isTrue != value)
{
_isTrue = value;
NotifyPropertyChanged("IsTrue");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
正如您在运行此操作时所看到的,当动画处于活动状态时,您的StaticResource
未被更新 - 当动画未激活时,它就是。这是因为动画运行时WPF为IsChecked
属性提供了一个新值(由Storyboard
定义)。这有效地破坏了旧的价值 - 双向Binding
到StaticResource
。动画完成并停止后,WPF会将旧值IsChecked
恢复为原始绑定表达式,因此您的资源MyBool
将继续接收更新。
可以在此处找到关于DependencyProperty
值优先级的精彩文章:
http://msdn.microsoft.com/en-us/library/ms743230.aspx
希望这有帮助!
答案 1 :(得分:1)
问题在于绑定,而不是在UI中。
您可以尝试在代码隐藏ThisCheckBox.IsChecked = true;
中设置IsChecked,如果您在XAML中绑定,这将被忽略!
XAML:
<Window x:Class="WpfApplication3.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<CheckBox x:Name="ThisCheckBox" IsChecked="{Binding IsTrue}" />
</Grid>
代码:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
this.DataContext = new CData();
ThisCheckBox.ClearValue(CheckBox.IsCheckedProperty);
//next will work only after clear binding
ThisCheckBox.IsChecked = true;
}
}
public class CData : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool _isTrue;
public bool IsTrue
{
get { return _isTrue; }
set
{
if (_isTrue != value)
{
_isTrue = value;
OnPropertyChanged(new PropertyChangedEventArgs("IsTrue"));
}
}
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, e);
}
}
}