2009-10-30 20 views
8

मैं एक एनीमेशन शुरू करने के लिए एक साफ तरीका ढूंढ रहा हूं जिसमें गतिशील मूल्य होंगे। असल में मैं एक एनीमेशन करना चाहता हूं जहां एक तत्व किसी अन्य तत्व के डेटा के आधार पर चौड़ाई बदलता है। मान लें कि मेरे पास टेक्स्टब्लॉक है जो टेक्स्ट प्रॉपर्टी बाध्यकारी है। जब यह संपत्ति बदलती है, तो मैं चाहता हूं कि एक दृश्य तत्व हमारे आय के लिए एक आयताकार कहता है, जो कि डबल वैनिएशन को पिछले मान से चौड़ाई को नए मान में बदलता है।डब्ल्यूपीएफ एमवीवीएम संपत्ति परिवर्तन एनीमेशन

यदि संभव हो तो मैं अपने दृश्य में कोड डालने से दूर रहने की कोशिश कर रहा हूं। मैंने डेटाट्रिगर्स में देखा है लेकिन उन्हें लगता है कि आप जानते हैं कि एनम जैसे मूल्य क्या होगा। मेरे मामले में यह केवल मूल्य बदल रहा है जिसे स्टोरीबोर्ड को ट्रिगर करने की आवश्यकता होती है और एनीमेशन को वर्तमान (पिछले) मान से शुरू करने और नए मूल्य पर अच्छी तरह से स्थानांतरित करने की आवश्यकता होगी।

कोई भी विचार। शायद मैं सिर्फ एक संपत्ति याद किया।

उत्तर

13

यहां समाधान है जिसके साथ मैं समाप्त हुआ। मेरे व्यूमोडेल में डेटा के आधार पर एनीमेशन करने के लिए मैंने डेटा ट्रिगर का उपयोग किया। नियंत्रण के लिए मेरी शैली नीचे है।

<Style TargetType="Grid" x:Key="DetailRotation" > 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding Path=AnimationState}" Value="New"> 
      <DataTrigger.EnterActions> 
       <StopStoryboard BeginStoryboardName="EndAnimation" /> 
       <BeginStoryboard Name="NewAnimation"> 
        <Storyboard> 
         <ThicknessAnimation Storyboard.TargetProperty="Margin" From="0,30,0,0" To="0,0,0,0" Duration="0:0:1" /> 
         <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1" /> 
        </Storyboard> 
       </BeginStoryboard> 
      </DataTrigger.EnterActions> 
      <DataTrigger.ExitActions> 

      </DataTrigger.ExitActions> 

     </DataTrigger> 
     <DataTrigger Binding="{Binding Path=AnimationState}" Value="End"> 
      <DataTrigger.EnterActions> 
       <StopStoryboard BeginStoryboardName="NewAnimation" /> 
       <BeginStoryboard Name="EndAnimation"> 
        <Storyboard> 
         <ThicknessAnimation Storyboard.TargetProperty="Margin" From="0,0,0,0" To="0,-20,0,0" Duration="0:0:1"/> 
         <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:1" /> 
        </Storyboard> 
       </BeginStoryboard> 
      </DataTrigger.EnterActions> 
     </DataTrigger> 

    </Style.Triggers> 
</Style> 
1

आप स्टोरीबोर्ड/एनिमेशन की आवश्यक तर्क को हुक करने के लिए Attached Properties का उपयोग करके एक्सप्लोर कर सकते हैं।

यह आपको कोड लिखने से रोक नहीं देगा, लेकिन यह इसे दृश्य से अलग रखेगा और इसे कई दृश्यों में फिर से उपयोग करने की अनुमति देगा।

+0

मुझे सच में यकीन नहीं है कि यह मेरी जरूरत है। मैं लगभग उस बिंदु पर हूं जहां मुझे स्टोरीबोर्ड को स्थानांतरित करने के लिए रूटरडेवेंट का उपयोग करना होगा और एनीमेशन के गुणों से और पिछली वाइडथ और वर्तमान विड्थ को बांधना होगा। ऐसा करने का यह एकमात्र तरीका हो सकता है। अभी भी निश्चित नहीं। डेटा ट्रिगर केवल राज्य शैली परिवर्तनों के लिए काम करेंगे जो गतिशील परिवर्तन नहीं हैं। यह वह जगह है जहां मैं थोड़ा पैटर्न से अलग हो जाता हूं। – cjibo

0

एनीमेशन द्वारा संशोधित गुण एनीमेशन 'संदर्भ' बाहर सेट नहीं किया जा सकता है के बाद से, मैं एक कोड समाधान के बाद से मैं प्रभावी रूप से XAML में एक ही नहीं कर सका के साथ आया था।

private void UserControl_IsVisibleChanged(object sender, 
    DependencyPropertyChangedEventArgs e) 
{ 
    if (this.Visibility == Visibility.Visible) 
    { 
     DoubleAnimation fadeIn = new DoubleAnimation(); 
     fadeIn.From = 1d; 
     fadeIn.To = 1d; 
     fadeIn.Duration = new Duration(new TimeSpan(0, 0, 0)); 

     DoubleAnimation fade = new DoubleAnimation(); 
     fade.From = 1d; 
     fade.To = 0d; 
     fade.BeginTime = TimeSpan.FromSeconds(5); 
     fade.Duration = new Duration(new TimeSpan(0, 0, 1)); 

     NameScope.SetNameScope(this, new NameScope()); 
     this.RegisterName(this.Name, this); 

     Storyboard.SetTargetName(fadeIn, this.Name); 
     Storyboard.SetTargetProperty(fadeIn, new PropertyPath 
      (UIElement.OpacityProperty)); 

     Storyboard.SetTargetName(fade, this.Name); 
     Storyboard.SetTargetProperty(fade, new PropertyPath 
      (UIElement.OpacityProperty)); 

     Storyboard sb = new Storyboard(); 
     sb.Children.Add(fadeIn); 
     sb.Children.Add(fade); 

     sb.Completed += new EventHandler(sb_Completed); 
     sb.Begin(this); 
    } 
} 

void sb_Completed(object sender, EventArgs e) 
{ 
    this.Visibility = Visibility.Hidden; 
} 
0

वास्तव में आप ViewModel संपत्ति को DoubleAnimation.ToProperty बाँध और वास्तविक नियंत्रण चेतन करना चाहते हैं। समस्या यह है कि ToProperty बदलते समय एनीमेशन जारी रखा जाना चाहिए। मेरा समाधान इस तर्क को MarkupExtenstion पर समाहित करता है जो Binding को लपेटता है।

public class AnimateBindingExtension : MarkupExtension { 
    static DependencyPropertyDescriptor dpd = 
     DependencyPropertyDescriptor.FromProperty(DoubleAnimation.ToProperty, 
      typeof(DoubleAnimation)); 

    public AnimateBindingExtension(PropertyPath path) { 
     Path = path; 
    } 

    public bool ValidatesOnExceptions { get; set; } 
    public IValueConverter Converter { get; set; } 
    public object ConverterParamter { get; set; } 
    public string ElementName { get; set; } 
    public RelativeSource RelativeSource { get; set; } 
    public object Source { get; set; } 
    public bool ValidatesOnDataErrors { get; set; } 
    [ConstructorArgument("path")] 
    public PropertyPath Path { get; set; } 
    public object TargetNullValue { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) { 
     var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; 

     if (valueProvider == null) { 
      throw new Exception("could not get IProviderValueTarget service."); 
     } 

     var bindingTarget = valueProvider.TargetObject as FrameworkElement; 
     var bindingProperty = valueProvider.TargetProperty as DependencyProperty; 

     if (bindingProperty == null || bindingTarget == null) { 
      throw new Exception(); 
     } 

     var binding = new Binding { 
      Path = Path, 
      Converter = Converter, 
      ConverterParameter = ConverterParamter, 
      ValidatesOnDataErrors = ValidatesOnDataErrors, 
      ValidatesOnExceptions = ValidatesOnExceptions, 
      TargetNullValue = TargetNullValue 
     }; 

     if (ElementName != null) binding.ElementName = ElementName; 
     else if (RelativeSource != null) binding.RelativeSource = RelativeSource; 
     else if (Source != null) binding.Source = Source; 

     // you can add a Duration property to this class and use it here 
     var anim = new DoubleAnimation { 
      Duration = new Duration(TimeSpan.FromSeconds(0.1)), 
      AccelerationRatio = 0.2, 
      DecelerationRatio = 0.8 
     }; 
     // this can be a new subclass of DoubleAnimation that 
     // overrides ToProperty metadata and add a property 
     // change callback 
     dpd.AddValueChanged(anim, (s, e) => bindingTarget.BeginAnimation(bindingProperty, anim)); 

     BindingOperations.SetBinding(anim, DoubleAnimation.ToProperty, binding); 
     // this is because we need to catch the DataContext so add animation object 
     // to the visual tree by adding it to target object's resources. 
     bindingTarget.Resources[bindingProperty.Name] = anim; 
     // animation will set the value 
     return DependencyProperty.UnsetValue; 
    } 
} 

आप अन्य प्रकार चेतन करने के लिए अन्य एनीमेशन वर्गों के साथ भी ऐसा ही कर सकते हैं।

+0

शैलियों/टेम्पलेट्स में रखे जाने पर यह ठंडे स्टोरीबोर्ड के साथ व्यापक मुद्दों में चलेगा? यदि बहुत दिलचस्प नहीं लग रहा है ... – tobriand

+0

Xaml में इस बाध्यकारी एक्सटेंशन का उपयोग करने के लिए वाक्यविन्यास क्या है? –

संबंधित मुद्दे