【问题标题】:Databinding not updating when changing through Storyboards?通过情节提要更改时数据绑定不更新?
【发布时间】:2012-01-16 17:03:33
【问题描述】:

我有一个 MyBool 类的实例,其属性为 IsTrue,存储为 StaticResource。而且我还有一个 CheckBox,其 IsChecked 属性绑定到类的实例。

{Binding IsTrue, Mode=TwoWay, Source={StaticResource MyBoolInstance}}

它工作正常。如果我更改 CheckBox 上的 check 属性,MyBool 的实例也会更新,反之亦然。

但是,如果我 通过 StoryBoard

操作 CheckBox 的 IsChecked 属性
<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 没有更新!

有什么建议或解决方法吗?

【问题讨论】:

  • 但是ThisCheckBox.IsChecked 属性确实发生了变化?您实际上想通过使用Storyboard 来实现什么?
  • 是的。我的思维方式有点错误,我正在尝试使用情节提要来更改 CheckBox 的 IsChecked 属性,希望它也会更改绑定的对象。
  • 如果你用动画设置IsChecked,你会覆盖你的绑定。您应该更改绑定源,而不是 CheckBox 本身。
  • 我现在明白了:D 你如何更新 XAML 中的绑定源?

标签: c# wpf binding storyboard


【解决方案1】:

这是一个完全重现您的问题的示例:

<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 定义)提供了一个新值。这有效地破坏了旧值 - 双向 BindingStaticResource。动画结束并停止后,WPF 会将 IsChecked 的旧值恢复为原始绑定表达式,因此您的资源 MyBool 将继续接收更新。

可以在此处找到有关 DependencyProperty 值优先级的精彩文章:

http://msdn.microsoft.com/en-us/library/ms743230.aspx

希望这会有所帮助!

【讨论】:

    【解决方案2】:

    问题在于绑定,而不是 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);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-29
      • 2016-08-07
      相关资源
      最近更新 更多