如何提高此控件的性能?

时间:2012-04-03 18:34:54

标签: c# wpf .net-4.0

我需要一个项目的选框,经过大量的谷歌搜索和反复试验,我创建了一个。然而,动画本身有点紧张。我需要一些关于如何提高性能的指针。谢谢。 附:有些代码可能是冗余的......

public class Marquee : Canvas
{
    static Marquee()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(Marquee), new FrameworkPropertyMetadata(typeof(Marquee)));
    }

    private IList<string> _lines = new List<string>();
    private IList<string> Lines
    {
        get
        {
            return _lines;
        }
        set
        {
            _lines = value;
        }
    }

    public double FontSize
    {
        get { return (double)GetValue(FontSizeProperty); }
        set { SetValue(FontSizeProperty, value); }
    }
    // Using a DependencyProperty as the backing store for FontSize.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FontSizeProperty =
        DependencyProperty.Register("FontSize", typeof(double), typeof(Marquee));

    public Brush FontBrush
    {
        get { return (Brush)GetValue(FontBrushProperty); }
        set { SetValue(FontBrushProperty, value); }
    }
    // Using a DependencyProperty as the backing store for FontBrush.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FontBrushProperty =
        DependencyProperty.Register("FontBrush", typeof(Brush), typeof(Marquee));

    public string SourceFile { get; set; }

    List<RenderTargetBitmap> _images = new List<RenderTargetBitmap>();
    private void CreateBitmaps()
    {
        foreach (var line in Lines)
        {
            FormattedText ft = new FormattedText(line,
            System.Globalization.CultureInfo.CurrentUICulture,
            System.Windows.FlowDirection.LeftToRight,
            new Typeface(FontFamily.Source),
            FontSize,
            FontBrush);

            if (ft.Height == 0 || ft.Width == 0)
                continue;

            DrawingVisual drawingVisual = new DrawingVisual();
            DrawingContext drawingContext = drawingVisual.RenderOpen();
            drawingContext.DrawText(ft, new Point(0, 0));
            drawingContext.Close();

            RenderTargetBitmap bmp = new RenderTargetBitmap((int)ft.Width, (int)ft.Height, 72, 72, PixelFormats.Pbgra32);
            bmp.Render(drawingVisual);
            bmp.Freeze();
            _images.Add(bmp);
        }

    }

    private int nextImgIndex = 0;
    private Image _Image;
    private void GetNextImage()
    {
        if (_images.Count == 0)
            return;
        if (nextImgIndex >= _images.Count)
            nextImgIndex = 0;

        _Image.Source = _images.ElementAt(nextImgIndex++);
    }

    private string _curStr = null;
    private string CurrentString
    {
        get
        {
            return _curStr;
        }
        set
        {
            _curStr = value;
        }
    }

    TextBlock _textBlock = new TextBlock();

    DispatcherTimer timer;

    public Marquee()
    {
        Loaded += Marquee_Loaded;

        FontSize = 12;
        FontBrush = Brushes.Black;

        if (Rate == 0d)
        {
            Rate = 150d;
        }

        this.CacheMode = new BitmapCache(2);
        FontBrush.Freeze();

        _Image = new Image();
        _Image.CacheMode = new BitmapCache();
        _Image.ClipToBounds = false;

        FontFamily = new FontFamily("Calibri");

        this.Children.Add(_Image);
    }

    void Marquee_Loaded(object sender, RoutedEventArgs e)
    {
        ReadFile();
        CreateBitmaps();
        CreateAnimation();
        //throw new NotImplementedException();
    }



    //[ValueConversion(typeof(string), typeof(TimeSpan))]
    //public class StringFormatConverter : IValueConverter
    //{
    //    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    //    {
    //        string[] vals = ((string)value).Split(new[] { ':' });
    //        if (vals.Count() != 3)
    //            throw new FormatException(string.Format("Invalid timespan format : {0}", value));
    //        return new TimeSpan(int.Parse(vals[0]), int.Parse(vals[1]), int.Parse(vals[2]));
    //    }

    //    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    //    {
    //        throw new NotImplementedException();
    //    }
    //}

    DoubleAnimation anim;
    TranslateTransform transform;
    Duration duration;

    public double Rate { get; set; }

    void CreateAnimation()
    {
        if (CurrentString == null)
            return;

        GetNextImage();

        transform = new TranslateTransform(Application.Current.MainWindow.ActualWidth, 0);

        _Image.RenderTransform = transform;

        var width = _Image.Source.Width;
        double secs = (Application.Current.MainWindow.ActualWidth + width) / Rate;

        duration = new Duration(TimeSpan.FromSeconds(secs));
        anim = new DoubleAnimation(-width, duration);
        anim.Completed += anim_Completed;
        transform.BeginAnimation(TranslateTransform.XProperty, anim);
    }

    void anim_Completed(object sender, EventArgs e)
    {
        CreateAnimation();
    }

    double MeasureStringLength(string text)
    {
        if (text == null)
            return 0;

        FormattedText ft = new FormattedText(text,
            System.Globalization.CultureInfo.CurrentUICulture,
            System.Windows.FlowDirection.LeftToRight,
            new Typeface(_textBlock.FontFamily.ToString()),
            FontSize,
            FontBrush);

        return ft.Width;
    }



    public FontFamily FontFamily
    {
        get { return (FontFamily)GetValue(FontFamilyProperty); }
        set { SetValue(FontFamilyProperty, value); }
    }

    // Using a DependencyProperty as the backing store for FontFamily.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FontFamilyProperty =
        DependencyProperty.Register("FontFamily", typeof(FontFamily), typeof(Marquee));

    FormattedText GetFormattedText(string text)
    {
        if (text == null)
            return null;

        FormattedText ft = new FormattedText(text,
            System.Globalization.CultureInfo.CurrentUICulture,
            System.Windows.FlowDirection.LeftToRight,
            new Typeface(_textBlock.FontFamily.ToString()),
            FontSize,
            FontBrush);

        return ft;
    }

    void ReadFile()
    {
        if (SourceFile == null)
            return;

        StreamReader fR = new StreamReader(SourceFile);
        string line;
        while ((line = fR.ReadLine()) != null)
        {
            Lines.Add(line);
        }

        if (Lines.Count > 0)
            CurrentString = Lines[0];
    }
}

1 个答案:

答案 0 :(得分:0)

我以下列方式修改了你的控件(删除变换动画,使用直接渲染而不是渲染到图像缓存):

public static readonly DependencyProperty OffsetProperty = DependencyProperty.Register("Offset", typeof(double),
    typeof(Marquee), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
//
public double Offset {
    get { return (double)GetValue(OffsetProperty); }
}
protected override void OnRender(DrawingContext dc) {
    dc.DrawText(currentText, new Point(Offset, 0)); // direct render
}
int nextTextIndex = 0;
FormattedText currentText;
void GetNextText() {
    if(formattedTexts.Count == 0) return;
    currentText = formattedTexts[(nextTextIndex++) % formattedTexts.Count];
}
void CreateAnimation() {
    if(CurrentString == null)
        return;
    GetNextText();
    double width = currentText.Width;
    double secs = (Application.Current.MainWindow.ActualWidth + width) / Rate;
    duration = new Duration(TimeSpan.FromSeconds(secs));
    anim = new DoubleAnimation(0, -width, duration);
    anim.Completed += anim_Completed;
    BeginAnimation(OffsetProperty, anim);
}
//
void anim_Completed(object sender, EventArgs e) {
    anim.Completed -= anim_Completed;
    CreateAnimation();
}

List<FormattedText> formattedTexts = new List<FormattedText>();
void CreateTexts() {
    foreach(var line in Lines) {
        FormattedText ft = new FormattedText(line,
            System.Globalization.CultureInfo.CurrentUICulture,
            System.Windows.FlowDirection.LeftToRight,
            new Typeface(FontFamily.Source),
            FontSize,
            FontBrush);

        if(ft.Height == 0 || ft.Width == 0)
            continue;
        formattedTexts.Add(ft);
    }
}

现在对我来说更顺畅。