Tôi có cùng một câu hỏi. Lợi thế của một cơ chế giống như thành phần là nhà thiết kế có thể thêm nó vào trong Blend, cấu hình nó trong trình thiết kế với trình soạn thảo Properties và sử dụng ràng buộc dữ liệu. Bạn nghĩ gì về giải pháp dưới đây? Nó hoạt động.
public class TimerComponent : FrameworkElement
{
public Timer Timer { get; protected set; }
public TimerComponent()
{
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
Visibility = Visibility.Collapsed;
Timer = new Timer(OnTimerTick, null, Timeout.Infinite, Timeout.Infinite);
}
}
void OnTimerTick(object ignore)
{
Dispatcher.BeginInvoke(new Action(RaiseTickEvent));
}
#region DueTime Dependency Property
public int DueTime
{
get { return (int)GetValue(DueTimeProperty); }
set { SetValue(DueTimeProperty, value); }
}
public static readonly DependencyProperty DueTimeProperty =
DependencyProperty.Register("DueTime", typeof(int), typeof(TimerComponent), new UIPropertyMetadata(new PropertyChangedCallback(OnDueTimeChanged)));
static void OnDueTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var target = obj as TimerComponent;
if (target.Timer != null)
{
var newDueTime = (int)e.NewValue;
target.Timer.Change(newDueTime, target.Period);
}
}
#endregion
#region Period Dependency Property
public int Period
{
get { return (int)GetValue(PeriodProperty); }
set { SetValue(PeriodProperty, value); }
}
public static readonly DependencyProperty PeriodProperty =
DependencyProperty.Register("Period", typeof(int), typeof(TimerComponent), new UIPropertyMetadata(new PropertyChangedCallback(OnPeriodChanged)));
static void OnPeriodChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var target = obj as TimerComponent;
if (target.Timer != null)
{
var newPeriod = (int)e.NewValue;
target.Timer.Change(target.DueTime, newPeriod);
}
}
#endregion
#region Tick Routed Event
public static readonly RoutedEvent TickEvent = EventManager.RegisterRoutedEvent(
"Tick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TimerComponent));
public event RoutedEventHandler Tick
{
add { AddHandler(TickEvent, value); }
remove { RemoveHandler(TickEvent, value); }
}
private void RaiseTickEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(TimerComponent.TickEvent);
RaiseEvent(newEventArgs);
}
#endregion
}
Và được sử dụng như sau.
<StackPanel>
<lib:TimerComponent Period="{Binding ElementName=textBox1, Path=Text}" Tick="OnTimerTick" />
<TextBox x:Name="textBox1" Text="1000" />
<Label x:Name="label1" />
</StackPanel>