2015-07-09 53 views
0

我原型鍵入(Windows 10通用應用程序)UI,並構建了一個非常簡單/粗糙的用戶控件以充當「徽章」,即在一個圓圈,並讓這個值變動。我的問題是控制工程,如果在應用程序頁面中只有一個實例。如果有多個實例(即使其他實例不可見),那麼只有最後一個聲明的實例動畫。用戶控制動畫僅適用於最後聲明的控件實例

我試過在用戶控件的XAML中聲明動畫,並在後面的代碼中嘗試確保沒有與共享的動畫交叉/混淆。我還添加了一個更改回調到正在動畫的屬性,該屬性使用Debug.WriteLine寫入屬性值。對於正確動畫化值的控件實例如預期那樣變化,即,如果我們從10變爲20,則屬性設置爲10,11,12,13 ... 20.對於不起作用的實例,值每次只設置爲from屬性,即10,10,10,10,10。

下面是一個用戶控件示例,然後是一個使用它的三個實例的示例頁面。放置這兩者都是一個新的Windows 10通用應用程序,名爲App3應該重現該問題。在示例頁面中,前兩個徽章在點擊按鈕時不會正確動畫,但最後一個徽標會執行動作。

是否有人能夠指出我做錯了什麼,以及爲什麼這打破了頁面上的多個實例?

謝謝。

注意:代碼變得非常粗糙,因爲我試圖找出問題所在,並且只是原型代碼,所以我爲這個混亂道歉。

<UserControl 
x:Class="App3.BadgeView" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:App3" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 
d:DesignHeight="20" 
d:DesignWidth="20"> 
<Grid> 
    <Ellipse x:Name="Border" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="{Binding BadgeBorderBrush}" /> 
    <Ellipse x:Name="BadgeInner" Margin="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="{Binding BadgeFillBrush}" /> 
    <TextBlock x:Name="BadgeValue" Margin="5" HorizontalAlignment="Center" FontSize="10" VerticalAlignment="Center" TextAlignment="Center" TextTrimming="CharacterEllipsis" Foreground="White" Text="{Binding DisplayValue}" /> 
</Grid> 

public sealed partial class BadgeView : UserControl 
{ 

    public DependencyProperty BadgeBorderBrushProperty = DependencyProperty.Register("BadgeBorderBrush", typeof(Brush), typeof(BadgeView), new PropertyMetadata(new SolidColorBrush(Windows.UI.Colors.Yellow))); 
    public DependencyProperty BadgeFillBrushProperty = DependencyProperty.Register("BadgeFillBrush", typeof(Brush), typeof(BadgeView), new PropertyMetadata(new SolidColorBrush(Windows.UI.Colors.Orange))); 

    public DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(BadgeView), new PropertyMetadata(0, new PropertyChangedCallback(ValueChanged))); 
    public DependencyProperty DisplayValueProperty = DependencyProperty.Register("DisplayValue", typeof(int), typeof(BadgeView), new PropertyMetadata(0, DisplayValueChanged)); 

    private static void DisplayValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine(((BadgeView)d).DisplayValue); 
    } 

    private Storyboard AnimateBadgeValueCount; 
    private DoubleAnimation BadgeValueAnimation; 

    public BadgeView() 
    { 
     this.InitializeComponent(); 
     this.BadgeValue.DataContext = this.BadgeInner.DataContext = this.Border.DataContext = this; 

     AnimateBadgeValueCount = new Storyboard(); ; 
     AnimateBadgeValueCount.Duration = TimeSpan.FromSeconds(0.5); 
     Storyboard.AllowDependentAnimations = true; 
     BadgeValueAnimation = new DoubleAnimation(); 
     BadgeValueAnimation.Duration = TimeSpan.FromSeconds(0.5); 
     BadgeValueAnimation.EnableDependentAnimation = true; 
     BadgeValueAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut }; 

     this.AnimateBadgeValueCount.FillBehavior = FillBehavior.Stop; 
     this.BadgeValueAnimation.FillBehavior = FillBehavior.Stop; 
     AnimateBadgeValueCount.Children.Add(BadgeValueAnimation); 

     Storyboard.SetTarget(AnimateBadgeValueCount, this); 
     Storyboard.SetTargetProperty(AnimateBadgeValueCount, "DisplayValue"); 

     this.AnimateBadgeValueCount.Completed += AnimateBadgeValueCount_Completed; 
    } 

    private void AnimateBadgeValueCount_Completed(object sender, object e) 
    { 
     this.DisplayValue = this.Value; 
    } 

    private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var badgeView = (BadgeView)d; 

     badgeView.AnimateValue(); 
    } 

    private void AnimateValue() 
    { 
     if (Value != DisplayValue) 
     { 
      this.BadgeValue.DataContext = this.BadgeInner.DataContext = this.Border.DataContext = this; 

      this.AnimateBadgeValueCount.Stop(); 
      this.BadgeValueAnimation.From = this.DisplayValue; 
      this.BadgeValueAnimation.To = this.Value; 
      this.BadgeValueAnimation.FillBehavior = FillBehavior.Stop; 
      //Storyboard.SetTarget(this.AnimateBadgeValueCount, this); 
      //Storyboard.SetTargetProperty(this.AnimateBadgeValueCount, "DisplayValue"); 
      this.AnimateBadgeValueCount.Begin(); 
     } 
    } 

    public Brush BadgeBorderBrush 
    { 
     get { return (Brush)this.GetValue(this.BadgeBorderBrushProperty); } 
     set 
     { 
      this.SetValue(this.BadgeBorderBrushProperty, value); 
     } 
    } 

    public Brush BadgeFillBrush 
    { 
     get { return (Brush)this.GetValue(this.BadgeFillBrushProperty); } 
     set 
     { 
      this.SetValue(this.BadgeFillBrushProperty, value); 
     } 
    } 

    public int Value 
    { 
     get { return (int)this.GetValue(ValueProperty); } 
     set 
     { 
      this.SetValue(ValueProperty, value); 
     } 
    } 

    public int DisplayValue 
    { 
     get { return (int)this.GetValue(DisplayValueProperty); } 
     set 
     { 
      this.SetValue(DisplayValueProperty, value); 
     } 
    } 

} 

<Page 
x:Class="App3.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:App3" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d"> 

<StackPanel Orientation="Vertical"> 
    <Button Content="Do it" x:Name="DoIt1" Click="DoIt1_Click" /> 
    <local:BadgeView x:Name="Badge1" Width="20" Height="20" BadgeFillBrush="Blue" /> 

    <Button Content="Do it" x:Name="DoIt2" Click="DoIt2_Click" /> 
    <local:BadgeView x:Name="Badge2" Width="20" Height="20" /> 

    <Button Content="Do it" x:Name="DoIt3" Click="DoIt3_Click" /> 
    <local:BadgeView x:Name="Badge3" Width="20" Height="20" /> 

</StackPanel> 

public sealed partial class MainPage : Page 
{ 
    public MainPage() 
    { 
     this.InitializeComponent(); 
    } 

    private void DoIt1_Click(object sender, RoutedEventArgs e) 
    { 
     this.Badge1.Value += 10; 
    } 

    private void DoIt2_Click(object sender, RoutedEventArgs e) 
    { 
     this.Badge2.Value += 10; 
    } 

    private void DoIt3_Click(object sender, RoutedEventArgs e) 
    { 
     this.Badge3.Value += 10; 
    } 
} 
+0

爲什麼要改變綁定的動畫效果你不試圖給BadgeValue.Text設置動畫效果嗎?它是在控制之內,你有舊值和新值,所以我認爲是合法的 –

+0

我相信我不能(至少不是直接),因爲.Text是一個字符串,並且doubleanimation不會動畫該類型。由於.Text可能不是一個數字,它不會知道如何增加它。另外,動畫適用於一個控件實例,所以我不認爲綁定是問題。 – Yort

+0

我知道這不是一個答案,但我總是發現用戶控件在xaml中由於DataContext問題而有點噩夢,並且始終偏好自定義控件。如果有興趣,我可以稍後舉一個簡單的例子,但並不真正回答你的問題 – SWilko

回答

1

我所做的是簡化代碼,並簡化移動DataContext的構造函數中加載的事件中:

this.Loaded += (s, e) => 
     { 
      this.DataContext = this; 

      AnimateBadgeValueCount = new Storyboard(); ; 
      AnimateBadgeValueCount.Duration = TimeSpan.FromSeconds(0.5); 
      BadgeValueAnimation = new DoubleAnimation(); 
      BadgeValueAnimation.Duration = TimeSpan.FromSeconds(0.5); 
      //BadgeValueAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut }; 
      AnimateBadgeValueCount.Children.Add(BadgeValueAnimation); 

      Storyboard.SetTarget(AnimateBadgeValueCount, this); 
      Storyboard.SetTargetProperty(AnimateBadgeValueCount, "DisplayValue"); 

      this.AnimateBadgeValueCount.Completed += AnimateBadgeValueCount_Completed; 
     }; 


private async void AnimateValue() 
    { 
     if (Value != DisplayValue) 
     { 
      this.AnimateBadgeValueCount.Stop(); 
      this.BadgeValueAnimation.From = this.DisplayValue; 
      this.BadgeValueAnimation.To = this.Value; 
      BadgeValueAnimation.EnableDependentAnimation = true; 

      await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High,() => 
      { 
       this.AnimateBadgeValueCount.Begin(); 
      }); 
     } 
    } 

我已評論EasingF聯合,它的作品,但在我看來適合更好。 這很好奇,因爲如果我只是在構造函數中設置datacontext,它工作不好,但裏面進行得很好。 如果您嘗試,請告訴我。

+0

謝謝。將datacontext賦值移動到加載的事件確實可以解決問題。我不知道爲什麼......你明白爲什麼這會有所作爲嗎? – Yort