При обновлении через раскадровку не обновляется привязка данных? - PullRequest
4 голосов
/ 09 декабря 2011

У меня есть экземпляр класса MyBool со свойством IsTrue , хранящимся как StaticResource .И у меня также есть CheckBox со свойством IsChecked, привязанным к экземпляру класса.

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

Работает нормально.Если я изменяю свойство check в CheckBox, обновляется также экземпляр MyBool и наоборот.

Однако, если я манипулирую свойством IsChecked CheckBox через a 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>

Свойство IsTrue экземпляра MyBool не обновляется!

Любые предложения или работы-обходные

Ответы [ 2 ]

3 голосов
/ 09 декабря 2011

Вот пример, который полностью воспроизводит вашу проблему:

<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 голос
/ 09 декабря 2011

Проблема в привязке , а не в пользовательском интерфейсе.Вы можете попробовать установить IsChecked в коде позади ThisCheckBox.IsChecked = true;, и это будет игнорироваться, если у вас есть привязка в 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);
        }
    }
}
...