C'est un moyen. C'est gentil et simple, mais un peu brouillon. Vous pouvez vous débarrasser du storyboard et à chaque tick, incrémenter une valeur locale par l'intervalle de tick et l'utiliser pour définir votre temps. Vous auriez alors seulement une pièce de temps. Ou ... Une manière plus élégante et réutilisable serait de créer une classe d'aide qui est un DependencyObject. Je voudrais également utiliser un StoryBoard avec un DoubleAnimation et lier le Storyboard.Target à une instance de DoubleTextblockSetter. Définissez la durée du storyboard sur votre temps et définissez la valeur sur votre temps en secondes. Voici le DoublerBlockSetterCode.
public class DoubleTextBlockSetter : DependencyObject
{
private TextBlock textBlock { get; private set; }
private IValueConverter converter { get; private set; }
private object converterParameter { get; private set; }
public DoubleTextBlockSetter(
TextBlock textBlock,
IValueConverter converter,
object converterParameter)
{
this.textBlock = textBlock;
this.converter = converter;
this.converterParameter = converterParameter;
}
#region Value
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(double),
typeof(DoubleTextBlockSetter),
new PropertyMetadata(
new PropertyChangedCallback(
DoubleTextBlockSetter.ValuePropertyChanged
)
)
);
private static void ValuePropertyChanged(
DependencyObject obj,
DependencyPropertyChangedEventArgs args)
{
DoubleTextBlockSetter control = obj as DoubleTextBlockSetter;
if (control != null)
{
control.OnValuePropertyChanged();
}
}
public double Value
{
get { return (double)this.GetValue(DoubleTextBlockSetter.ValueProperty); }
set { base.SetValue(DoubleTextBlockSetter.ValueProperty, value); }
}
protected virtual void OnValuePropertyChanged()
{
this.textBlock.Text = this.converter.Convert(
this.Value,
typeof(string),
this.converterParameter,
CultureInfo.CurrentCulture) as string;
}
#endregion
}
alors vous pourriez avoir un convertisseur de format:
public class TicksFormatConverter : IValueConverter
{
TimeSpanFormatProvider formatProvider = new TimeSpanFormatProvider();
public object Convert(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
long numericValue = 0;
if (value is int)
{
numericValue = (long)(int)value;
}
else if (value is long)
{
numericValue = (long)value;
}
else if (value is double)
{
numericValue = (long)(double)value;
}
else
throw new ArgumentException("Expecting type of int, long, or double.");
string formatterString = null;
if (parameter != null)
{
formatterString = parameter.ToString();
}
else
{
formatterString = "{0:H:m:ss}";
}
TimeSpan timespan = new TimeSpan(numericValue);
return string.Format(this.formatProvider, formatterString, timespan);
}
public object ConvertBack(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
J'ai presque oublié le TimespanFormatProvider. Il n'y a pas de fournisseur de format pour la période dans Silverlight, donc il apparaît.
public class TimeSpanFormatProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType != typeof(ICustomFormatter))
return null;
return this;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
string formattedString;
if (arg is TimeSpan)
{
TimeSpan ts = (TimeSpan)arg;
DateTime dt = DateTime.MinValue.Add(ts);
if (ts < TimeSpan.FromDays(1))
{
format = format.Replace("d.", "");
format = format.Replace("d", "");
}
if (ts < TimeSpan.FromHours(1))
{
format = format.Replace("H:", "");
format = format.Replace("H", "");
format = format.Replace("h:", "");
format = format.Replace("h", "");
}
// Uncomment of you want to minutes to disappear below 60 seconds.
//if (ts < TimeSpan.FromMinutes(1))
//{
// format = format.Replace("m:", "");
// format = format.Replace("m", "");
//}
if (string.IsNullOrEmpty(format))
{
formattedString = string.Empty;
}
else
{
formattedString = dt.ToString(format, formatProvider);
}
}
else
throw new ArgumentNullException();
return formattedString;
}
}
Tout ce matériel est réutilisable et devrait se trouver dans votre boîte à outils. Je l'ai tiré du mien. Ensuite, bien sûr, vous branchez tous ensemble:
Storyboard sb = new Storyboard();
DoubleAnimation da = new DoubleAnimation();
sb.Children.Add(da);
DoubleTextBlockSetter textBlockSetter = new DoubleTextBlockSetter(
Your_TextBlock,
new TicksFormatConverter(),
"{0:m:ss}"); // DateTime format
Storyboard.SetTarget(da, textBlockSetter);
da.From = Your_RefreshInterval_Secs * TimeSpan.TicksPerSecond;
da.Duration = new Duration(
new TimeSpan(
Your_RefreshInterval_Secs * TimeSpan.TicksPerSecond));
sb.begin();
Et cela devrait faire l'affaire. C'est juste comme un million de lignes de code. Et nous n'avons même pas encore écrit Hello World ...;) Je n'ai pas compilé cela, mais j'ai copié et collé les 3 classes directement depuis ma bibliothèque. Je les ai beaucoup utilisés. Cela fonctionne très bien. J'utilise aussi ces classes pour d'autres choses. Le TickFormatConverter est pratique lors de la liaison de données. J'en ai aussi un qui fait des secondes. Très utile. Le DoubleTextblockSetter me permet d'animer des nombres, ce qui est vraiment amusant. Surtout quand vous appliquez différents types d'interpolation.
Profitez-en.
J'ai adoré la visualisation de la course. Bien joué. – caryden