Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
264 views
in Technique[技术] by (71.8m points)

wpf - How do you animate a line on a canvas in C#?

How would you make a line slowly draw across the screen?

I am trying to animate a line on a canvas in a C#/WPF project.

I would like to use C# code and not XAML.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I Have a running sample that uses the MVVM Pattern and creates Lines within a ListBox that has a Canvas as its ItemsPanel.

I actually made it for this question, but the OP kind of dissapeared and never contacted me about it.

This is what it looks like in my computer:

enter image description here

The main part of it is this:

<ListBox ItemsSource="{Binding}" x:Name="lst" Height="500" Width="500">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="FocusVisualStyle">
                <Setter.Value>
                    <Style TargetType="Control">
                        <Setter Property="Opacity" Value="0"/>
                    </Style>
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <Line X1="{Binding X1}" Y1="{Binding Y1}"
                              X2="{Binding X2}" Y2="{Binding Y2}" 
                              StrokeThickness="{Binding Thickness}"
                              Opacity="{Binding Opacity}"
                              x:Name="Line">
                            <Line.Stroke>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                                    <GradientStop Color="{Binding Color1}" Offset="0"/>
                                    <GradientStop Color="{Binding Color2}" Offset="1"/>
                                </LinearGradientBrush>
                            </Line.Stroke>
                        </Line>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="true">
                                <Setter Property="Effect" TargetName="Line">
                                    <Setter.Value>
                                        <DropShadowEffect Color="CornflowerBlue" ShadowDepth="3" BlurRadius="10"/>
                                    </Setter.Value>
                                </Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

ViewModel:

public class LineViewModel : INotifyPropertyChanged
{
    #region Timer-based Animation

    private System.Threading.Timer Timer;
    private static Random Rnd = new Random();

    private bool _animate;
    public bool Animate
    {
        get { return _animate; }
        set
        {
            _animate = value;
            NotifyPropertyChanged("Animate");
            if (value)
                StartTimer();
            else
                StopTimer();
        }
    }

    private int _animationSpeed = 1;
    public int AnimationSpeed
    {
        get { return _animationSpeed; }
        set
        {
            _animationSpeed = value;
            NotifyPropertyChanged("AnimationSpeed");
            if (Timer != null)
                Timer.Change(0, 100/value);
        }
    }

    private static readonly List<int> _animationSpeeds = new List<int>{1,2,3,4,5};
    public List<int> AnimationSpeeds
    {
        get { return _animationSpeeds; }
    }

    public void StartTimer()
    {
        StopTimer();
        Timer = new Timer(x => Timer_Tick(), null, 0, 100/AnimationSpeed);
    }

    public void StopTimer()
    {
        if (Timer != null)
        {
            Timer.Dispose();
            Timer = null;
        }
    }

    private void Timer_Tick()
    {
        X1 = X1 + Rnd.Next(-2, 3);
        Y1 = Y1 + Rnd.Next(-2, 3);
        X2 = X2 + Rnd.Next(-2, 3);
        Y2 = Y2 + Rnd.Next(-2, 3);
    }

    #endregion

    #region Coordinates

    private double _x1;
    public double X1
    {
        get { return _x1; }
        set
        {
            _x1 = value;
            NotifyPropertyChanged("X1");
        }
    }

    private double _y1;
    public double Y1
    {
        get { return _y1; }
        set
        {
            _y1 = value;
            NotifyPropertyChanged("Y1");
        }
    }

    private double _x2;
    public double X2
    {
        get { return _x2; }
        set
        {
            _x2 = value;
            NotifyPropertyChanged("X2");
        }
    }

    private double _y2;
    public double Y2
    {
        get { return _y2; }
        set
        {
            _y2 = value;
            NotifyPropertyChanged("Y2");
        }
    }

    #endregion

    #region Other Properties

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            NotifyPropertyChanged("Name");
        }
    }

    private double _thickness;
    public double Thickness
    {
        get { return _thickness; }
        set
        {
            _thickness = value;
            NotifyPropertyChanged("Thickness");
        }
    }

    public Color Color1 { get; set; }
    public Color Color2 { get; set; }

    private double _opacity = 1;
    public double Opacity
    {
        get { return _opacity; }
        set
        {
            _opacity = value;
            NotifyPropertyChanged("Opacity");
        }
    }

    #endregion

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        Application.Current.Dispatcher.BeginInvoke((Action)(() =>
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }));
    }

    #endregion
}

Edit: Source code now on GitHub


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...