2011-10-11 11 views
6

Mam wyzwalacz danych WPF, który jest uruchamiany, gdy wartość jest prawdą.Wyzwalacz danych WPF nie uruchamia się, jeśli wartość pozostaje taka sama

Chcę, aby wyzwalacz uruchamiał się za każdym razem, gdy ta wartość jest ustawiona na wartość true, nawet jeśli była wcześniej prawdą. Niestety wydaje się, że wystrzeliwuje tylko wtedy, gdy wartość zmieni się z true na false lub vice versa. Mój bazowy model danych uruchamia zdarzenie PropertyChanged z INotifyPropertyChanged, nawet jeśli wartość jest ustawiona na true dwa razy z rzędu, ale Trigger nie wydaje się tego odbierać.

Czy mimo to należy uruchomić wyzwalacz, niezależnie od tego, czy zmieniona wartość została zmieniona?

Niektórzy z was prosili o kod, więc oto jest. Interesujące jest to, że konwertery będą wywoływane za każdym razem. Problem jest bardziej szczegółowy w przypadku uruchamiania animacji.

Aktualizacja Jeśli zmienię mojego kodu, aby zresetować wartość false, a następnie z powrotem na true znowu nie uruchamia animację. Oczywiście nie jest to idealne i nie czyni kodu przyjemnym do czytania. Mam nadzieję, że jest lepszy sposób na zrobienie tego.

Każda pomoc bardzo ceniona.

kod WPF

<Grid> 
    <Grid.Resources>    
     <Storyboard x:Key="AnimateCellBlue"> 
      <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Transparent" To="Blue" Duration="0:0:0.1" AutoReverse="True" RepeatBehavior="1x" /> 
     </Storyboard> 
    </Grid.Resources> 
    <TextBox Name="txtBox" Text="{Binding DataContext.DisplayText, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">   
     <TextBox.Style> 
      <Style TargetType="TextBox"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding DataContext.IsTrue, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Value="True"> 
         <DataTrigger.EnterActions>               
          <BeginStoryboard Name="BidSizeUpStoryB" Storyboard="{StaticResource AnimateCellBlue}" /> 
         </DataTrigger.EnterActions> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </TextBox.Style> 
    </TextBox> 
</Grid> 

Code Behind: -

public partial class MainWindow : Window 
{ 
    private DataItem _dataItem; 
    private DispatcherTimer _dispatcherTimer; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     _dataItem = new DataItem(); 
     _dataItem.DisplayText = "Testing"; 
     _dataItem.IsTrue = true; 

     this.DataContext = _dataItem; 

     _dispatcherTimer = new DispatcherTimer(TimeSpan.FromSeconds(1), DispatcherPriority.Normal, TimerCallbackHandler, Dispatcher); 

    } 

    private void TimerCallbackHandler(object s, EventArgs args) 
    { 
     Console.WriteLine("In Timer"); 
     _dataItem.IsTrue = true; 
     _dataItem.DisplayText = "Timer " + DateTime.Now.Ticks; 
    } 
} 

DataItem: -

public class DataItem : INotifyPropertyChanged 
{ 
    private bool _isTrue; 
    private string _displayText; 

    public bool IsTrue 
    { 
     get { return _isTrue; } 
     set 
     { 
      _isTrue = value; 
      NotifyPropertyChanged("IsTrue"); 
     } 
    } 

    public string DisplayText 
    { 
     get 
     { 
      return _displayText; 
     } 
     set 
     { 
      _displayText = value; 
      NotifyPropertyChanged("DisplayText"); 
     } 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 

    private void NotifyPropertyChanged(string info) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
    } 
} 
+1

Pokaż nam kod nieruchomości i spust, abyśmy nie musieli zgadywać. –

+0

Proszę zobaczyć mój przykładowy kod powyżej. Animacja zostanie uruchomiona tylko raz. – user630190

Odpowiedz

1

Spust będzie ogień, niezależnie od ustawionej wartości. Ilekroć zdarzenie PropertyChanged zostanie podniesione dla właściwości powiązanej z wyzwalaczem, wyzwalacz zostanie wywołany. Oto próbki, na którym mam zweryfikowaną -

<TextBox> 
    <TextBox.Style> 
     <Style TargetType="TextBox"> 
      <Style.Triggers> 
      <DataTrigger Binding="{Binding DataContext.IsTrue, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, 
                 Converter={StaticResource MyConverter}}" Value="True"> 
        <Setter Property="Background" Value="Red"/> 
      </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </TextBox.Style> 
</TextBox> 

umieścić punkt przerwania na moim konwerterze i zrobiło się nazywa Ilekroć podnieść zdarzenie PropertyChanged dla własności IsTrue. There msut być inny problem w kodzie. Czy możesz pokazać trochę swojego kodu, w którym znajduje się ten problem?

+0

Proszę zobaczyć moje pytanie z próbką kodu. To animacja, która nie strzela – user630190

0

Aktualizacja: wydaje się, że moja pierwsza odpowiedź była zależna od moich ValueConverters. Tak więc, zrobiłem trochę więcej badań i odkryłem ConditionalBehavior and PropertyChangedTrigger

Oto jeden, który przetestowałem.

<UserControl 
      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:i="http://schemas.microsoft.com/expression/2010/interactivity" 
      xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
      x:Class="WpfControlLibrary1.UserControl1" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <UserControl.Triggers> 
     <EventTrigger RoutedEvent="FrameworkElement.Loaded"/> 
    </UserControl.Triggers> 
    <Grid> 
     <i:Interaction.Triggers> 
      <!--Use multiple PropertyChangedTriggers to handle multiple conditions--> 
      <!--True State--> 
      <ei:PropertyChangedTrigger Binding="{Binding DataContext.IsTrue, 
        RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}" > 
       <i:Interaction.Behaviors> 
        <!--This is just a humble demonstration of Conditional Behavior, it's has so much potential that you can replicate complex if conditions--> 
        <ei:ConditionBehavior> 
         <ei:ConditionalExpression ForwardChaining="And"> 
          <ei:ComparisonCondition Operator="Equal" 
           LeftOperand="{Binding DataContext.IsTrue, RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}" 
           RightOperand="True" 
          /> 
         </ei:ConditionalExpression> 
        </ei:ConditionBehavior> 
       </i:Interaction.Behaviors> 
       <!--I'm not sure why, but I needed to apply the default state first so that the true state plays it's storyboard.--> 
       <!--If you don't do this, this behaves like a data trigger.--> 
       <ei:GoToStateAction StateName="DefaultState"/> 
       <ei:GoToStateAction StateName="TrueState"/> 
      </ei:PropertyChangedTrigger> 

      <!--False state--> 
      <ei:PropertyChangedTrigger Binding="{Binding DataContext.IsTrue, 
        RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}" > 
       <i:Interaction.Behaviors> 
        <ei:ConditionBehavior> 
         <ei:ConditionalExpression ForwardChaining="And"> 
          <ei:ComparisonCondition Operator="Equal" 
           LeftOperand="{Binding DataContext.IsTrue, RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}" 
           RightOperand="False" 
          /> 
         </ei:ConditionalExpression> 
        </ei:ConditionBehavior> 
       </i:Interaction.Behaviors> 
       <ei:GoToStateAction StateName="DefaultState"/> 
      </ei:PropertyChangedTrigger> 
     </i:Interaction.Triggers> 
     <VisualStateManager.VisualStateGroups> 
      <VisualStateGroup x:Name="VisualStateGroup"> 
       <VisualState x:Name="DefaultState"/> 
       <VisualState x:Name="TrueState"> 
        <Storyboard Storyboard.TargetName="txtBox" > 
         <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Transparent" To="Blue" Duration="0:0:0.1" AutoReverse="True" RepeatBehavior="1x" /> 
        </Storyboard> 
       </VisualState> 
      </VisualStateGroup> 
     </VisualStateManager.VisualStateGroups> 
     <TextBox x:Name="txtBox" Text="{Binding DataContext.DisplayText, RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}"/> 
    </Grid> 
</UserControl> 

Możesz użyć do tego grupy wizualnych stanów. Co więcej, właściwość i wartość zachowania mogą być zarówno danymi, jak i danymi!

Zrobiłem to szybko w mieszance i nie testowałem. to jest podobne do mojego rozwiązania.

<UserControl 
      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:i="http://schemas.microsoft.com/expression/2010/interactivity" 
      xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
      x:Class="WpfControlLibrary1.UserControl1" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
     <i:Interaction.Behaviors> 
      <ei:DataStateBehavior Binding="{Binding DataContext.IsTrue, 
        RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}" 
       Value="True" 
       TrueState="TrueState"/> 
     </i:Interaction.Behaviors> 
     <VisualStateManager.VisualStateGroups> 
      <VisualStateGroup x:Name="VisualStateGroup"> 
       <VisualState x:Name="DefaultState"/> 
       <VisualState x:Name="TrueState"> 
        <Storyboard Storyboard.TargetName="txtBox" > 
         <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Transparent" To="Blue" Duration="0:0:0.1" AutoReverse="True" RepeatBehavior="1x" /> 
        </Storyboard> 
       </VisualState> 
      </VisualStateGroup> 
     </VisualStateManager.VisualStateGroups> 
     <TextBox x:Name="txtBox" Text="{Binding DataContext.DisplayText, RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}"/> 
    </Grid> 
</UserControl> 
Powiązane problemy