2011-01-05 34 views
6

Tôi có vấn đề đang giết chết tôi. Dưới đây là ví dụ đơn giảnTại sao sau khi thiết lập chiều cao hoạt ảnh, thuộc tính này trực tiếp ngừng hoạt động

<Grid Name="_grid"> 
    <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="36,33,0,0" Name="button" VerticalAlignment="Top" Width="75" /> 
    <Button Content="Enlarge through animation" Height="23" Margin="172,33,24,0" Name="_animateButton" VerticalAlignment="Top" Click="_animateButton_Click" /> 
    <Button Content="Enlarge through simple heigh changing" Height="23" Margin="172,62,24,0" Name="_resizeButton" VerticalAlignment="Top" Click="_resizeButton_Click" /> 
</Grid> 

Và trong mã đằng sau

private void _resizeButton_Click(object sender, RoutedEventArgs e) 
{ 
    button.Height += 10; 
} 

private void _animateButton_Click(object sender, RoutedEventArgs e) 
{ 
    Storyboard storyboard = new Storyboard(); 

    DoubleAnimation animation = new DoubleAnimation(button.Height + 10, new Duration(new TimeSpan(0, 0, 0, 1))); 
    storyboard.Children.Add(animation); 

    Storyboard.SetTargetName(animation, button.Name); 
    Storyboard.SetTargetProperty(animation, new PropertyPath(HeightProperty)); 

    storyboard.Begin(_grid); 
} 

ứng dụng trông như thế này

alt text

Sau khi nhấn _resizeButton trái nút phóng to ngay lập tức. Sau đó, tôi nhấn _animateButton - nút bên trái là mở rộng chậm. Sau này tôi đang nhấn _resizeButton một lần nữa và không có gì đang xảy ra. Tại sao vậy?

tôi đã nhận thấy rằng điều tương tự là khi hiệu ứng động trên tài sản

Trả lời

15

Để hiểu hành vi, bạn cần biết tính năng hoạt ảnh trong hệ thống thuộc tính của WPF: hoạt ảnh không hoạt động bằng cách đặt thuộc tính thành các giá trị khác nhau theo thời gian. Chúng hoạt động bằng cách cung cấp giá trị hiệu quả cho thuộc tính tạm thời được ưu tiên hơn giá trị 'cơ sở'. Đây là một sự phân biệt tinh tế, nhưng đó là những gì khiến bạn đến đây.

Khi lần đầu tiên gặp phải hệ thống hoạt ảnh, hầu hết mọi người tưởng tượng rằng nó hoạt động bằng cách liên tục gọi bộ truy cập 'đặt' cho thuộc tính. Nhưng nó không - nếu bạn thiết lập thuộc tính theo cách đó trước khi bắt đầu hoạt ảnh vẫn còn, giá trị ban đầu bạn đặt vẫn giữ nguyên. Nó chỉ là getter sẽ trả về giá trị được cung cấp bởi hệ thống hoạt hình tùy chọn để trả về giá trị 'cục bộ'. Trong thực tế, bạn thậm chí có thể thay đổi giá trị 'cục bộ' bằng cách đặt thuộc tính trong khi hoạt ảnh đang chạy, nhưng giá trị cục bộ đó sẽ không hiển thị cho đến khi hoạt ảnh dừng lại.

Thực ra, hệ thống thuộc tính thực hiện rất nhiều thứ như vậy - không chỉ là hoạt ảnh. Điều này help topic liệt kê 11 địa điểm khác nhau mà giá trị của một tài sản có thể đến từ đó. Ảnh động là ưu tiên cao thứ 2. Các thuộc tính được đặt theo kiểu thông thường thông qua bộ truy cập 'set' (hoặc thông qua thuộc tính trong Xaml) là ưu tiên cao nhất tiếp theo, nhưng bạn có thể thấy các mẫu, kiểu và trình kích hoạt cung cấp các nguồn khác khi không có giá trị thuộc tính cục bộ.

Hệ thống hoạt ảnh trong WPF có khái niệm về giá trị 'cơ sở' và đó là giá trị ưu tiên cao nhất tiếp theo có sẵn sau giá trị hoạt ảnh hiện tại. Nếu bạn có một giá trị cục bộ, đó sẽ là giá trị cơ sở, nhưng nếu bạn không có giá trị cơ sở sẽ đến từ một trong các nguồn khác được liệt kê trong bài viết đó.

Kết quả của tất cả những điều đó là không có cách nào đơn giản để làm những gì bạn có vẻ đang cố gắng làm. Tôi nghĩ rằng những gì bạn muốn là cho các hình ảnh động để chạy để hoàn thành, và cho tài sản để giữ lại giá trị hoạt hình cuối cùng của nó cho đến khi bạn thiết lập giá trị địa phương cho cái gì khác.

Nếu bạn yêu cầu dừng hoạt ảnh sau khi hoàn thành, giá trị hiệu dụng sẽ trả lại giá trị cơ sở. Và nếu bạn bảo hoạt ảnh được giữ lại sau khi hoàn thành (đó là hành vi mặc định), thì hoạt ảnh sẽ mãi mãi cung cấp một giá trị có ưu tiên cao hơn các giá trị cục bộ , đó là lý do tại sao bạn thấy rằng việc thay đổi kích thước nút theo cách thủ công không còn hoạt động nữa. Vì vậy, không có tùy chọn nào làm những gì bạn muốn.

Có hai cách để giải quyết vấn đề này. @ responderNS5 đã đăng một - xử lý việc hoàn thành hoạt ảnh, sửa đổi giá trị cục bộ để phản ánh giá trị cuối cùng của hoạt ảnh và sau đó dừng hoạt ảnh. (Bạn có thể coi đây là một loại demotion của thuộc tính - nó chuyển đổi nó từ một giá trị đặc tính ưu tiên cao nhưng có độ phân giải cao được cung cấp thành giá trị cục bộ ưu tiên thấp hơn nhưng lại bền hơn). mã một chút:

private void myDoubleAnimation_Completed(object sender, EventArgs e) 
{ 
    // Animation complete, but holding, so Height will currently return 
    // return the final animated value. 
    double finalHeight = button.Height; 

    // Remove the animation. 
    button.BeginAnimation(Button.HeightProperty, null); 

    // Modify the local value to be the same as the final animated value. 
    button.Height = finalHeight; 
} 

Điều tôi đã thay đổi ở đây là mã không còn cố gắng đoán hệ thống hoạt ảnh đã kết thúc ở đâu nữa giá trị địa phương mới. Tôi thích điều đó với số += 10 trong trình xử lý Completed, điều này có vẻ giống như sự trùng lặp hơi mỏng manh đối với tôi.

Một cách khác để đối phó với nó là để loại bỏ các hình ảnh động tại điểm mà tại đó bạn cố gắng cập nhật tài sản:

Điều này có vẻ hơi mạnh mẽ hơn đối với tôi, vì điều này sẽ làm việc ngay cả khi hoạt ảnh chưa hoàn tất vào lúc bạn nhấp vào nút thay đổi kích thước.

3

Bạn cần phải đặt FillBehavior của DoubleAnimation để Stop thay vì Hold. Xem bài viết này:

+0

Cảm ơn câu trả lời của bạn nhưng sau khi đặt hoạt ảnh.FillBehavior = FillBehavior.Stop co lại về giá trị độ cao cuối cùng. Tôi có làm điều gì sai? – bizon

+0

Cảm ơn bạn !!! Đã lưu tôi giờ! – Rocklan

3

câu trả lời Rick sẽ không làm việc như bạn chỉ nó ra. Trong trường hợp của bạn, bạn cần phải thiết lập các hình ảnh động của các tài sản hoạt hình (chiều cao của nút) để null để bạn có thể thực hiện sửa đổi thêm về tài sản này.

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

private void _animateButton_Click(object sender, RoutedEventArgs e) 
    { 
     DoubleAnimation animation = new DoubleAnimation(); 
     animation.By = 10; 
     animation.Duration = new Duration(TimeSpan.FromSeconds(1)); 
     animation.Completed += new EventHandler(myDoubleAnimation_Completed); 
     button.BeginAnimation(Button.HeightProperty, animation); 
    } 

    private void myDoubleAnimation_Completed(object sender, EventArgs e) 
    { 
     button.BeginAnimation(Button.HeightProperty, null); 
     button.Height += 10; 
    } 

Thay đổi _animateButton_Click xử lý của bạn đến một trong những trình bày ở trên. Ngoài ra, thêm trình xử lý sự kiện thứ hai để khi hoạt ảnh hoàn tất, chúng ta có thể loại bỏ tham chiếu đến "hoạt ảnh" Câu lệnh thứ hai trong myDoubleAnimation_Completed là do khi tham chiếu hoạt ảnh bị xóa, giá trị không hoạt ảnh xuất hiện trở lại.

+0

Hoàn hảo .. Có một số bài đăng khác không có câu trả lời cho điều này. Tôi sẽ đặt liên kết đến câu trả lời của bạn – Sayka

Các vấn đề liên quan