我正在尝试制作一个WPF用户控件,该控件可以倒计时到特定日期,并在剩下指定的时间跨度时将文本变为红色以提醒用户。
当我传入静态参数时,我的代码按计划工作。 传递绑定参数时,我的代码失败。
这是我的主叫代码;
<!-- WORKS (STATIC PARAMETERS) -->
<controls:TextEditDateCountDown
AlertAtMinutesLeft="2100"
DateStampCountDownTo="{Binding Source={x:Static system:DateTime.Now},StringFormat='HH:mm:ss tt'}" />
<!-- DOES NOT WORK (BOUND PARAMETERS) -->
<controls:TextEditDateCountDown
AlertAtMinutesLeft="2100"
DateStampCountDownTo="{Binding Entity.MarketDescription.SuspendTime,Mode=OneTime}"/>
<!-- DOES NOT WORKING (BOUND PARAMETERS TRYING PRIORITY BINDING AS AT http://www.blackwasp.co.uk/WPFPriorityBinding.aspx) -->
<controls:TextEditDateCountDown
AlertAtMinutesLeft="2100">
<controls:TextEditDateCountDown.DateStampCountDownTo>
<PriorityBinding>
<Binding Path="Entity.MarketDescription.SuspendTime" Mode="OneTime" IsAsync="True"/>
<Binding Path="Entity.MarketId" Mode="OneTime" IsAsync="True"/>
</PriorityBinding>
</controls:TextEditDateCountDown.DateStampCountDownTo>
</controls:TextEditDateCountDown>
控制代码如下所示;
<!-- THE XAML -->
<Grid>
<dxe:TextEdit
x:Name="myTextEdit"
IsPrintingMode="True"
Mask="dd\d HH\h mm\m ss\s"
MaskType="DateTimeAdvancingCaret"
MaskUseAsDisplayFormat="True">
<dxe:TextEdit.Style>
<Style TargetType="dxe:TextEdit">
<Style.Triggers>
<DataTrigger Value="True" Binding="{Binding IsAlertOn, RelativeSource={RelativeSource AncestorType=controls:TextEditDateCountDown},Mode=OneTime}">
<Setter Property="Foreground" Value="Red" />
<Setter Property="FontWeight" Value="Bold" />
</DataTrigger>
<DataTrigger Value="False" Binding="{Binding IsAlertOn, RelativeSource={RelativeSource AncestorType=controls:TextEditDateCountDown},Mode=OneTime}"> <Setter Property="Foreground" Value="Black" />
<Setter Property="FontWeight" Value="Regular" />
</DataTrigger>
</Style.Triggers>
</Style>
</dxe:TextEdit.Style>
</dxe:TextEdit>
</Grid>
<!-- THE CODE BEHIND -->
public partial class TextEditDateCountDown : UserControl {
public TextEditDateCountDown() {
InitializeComponent();
timer.Interval = new TimeSpan(0, 0, 1);
timer.Tick += Timer_Tick;
timer.Start();
}
DispatcherTimer timer = new DispatcherTimer();
public static readonly DependencyProperty DateStampCountDownToProperty = DependencyProperty.Register("DateStampCountDownTo", typeof(DateTime), typeof(TextEditDateCountDown), new PropertyMetadata(DateTime.MinValue, CountDownToChanged));
public static readonly DependencyProperty AlertAtMinutesLeftProperty = DependencyProperty.Register("AlertAtMinutesLeft", typeof(string), typeof(TextEditDateCountDown), new PropertyMetadata(string.Empty, Changed));
public static readonly DependencyProperty IsAlertOnProperty = DependencyProperty.Register("IsAlertOn", typeof(bool), typeof(TextEditDateCountDown), new PropertyMetadata(false));
public DateTime? DateStampCountDownTo {
get {
return (DateTime?)GetValue(DateStampCountDownToProperty);
}
set { SetValue(DateStampCountDownToProperty, value); }
}
public virtual string AlertAtMinutesLeft {
get {
return (string)GetValue(AlertAtMinutesLeftProperty);
}
set { SetValue(AlertAtMinutesLeftProperty, value); }
}
public bool IsAlertOn {
get { return (bool)GetValue(IsAlertOnProperty); }
set { SetValue(IsAlertOnProperty, value); }
}
private bool UpdateIsAlertOn(string value) {
if (value != null && value != "") {
int i = int.Parse(AlertAtMinutesLeft);
return DateTime.Now > DateStampCountDownTo.Value.AddMinutes(i);
} else
return false;
}
private DateTime? UpdateDateStampCountDownTo(DateTime? value) {
return DateStampCountDownTo.Value;
}
private static void Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var textEditControl = d as TextEditDateCountDown;
if (textEditControl == null) return;
textEditControl.IsAlertOn = textEditControl.UpdateIsAlertOn(textEditControl.AlertAtMinutesLeft);
}
private static void CountDownToChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var textEditControl = d as TextEditDateCountDown;
if (textEditControl == null) return;
textEditControl.DateStampCountDownTo = textEditControl.UpdateDateStampCountDownTo(textEditControl.DateStampCountDownTo);
}
void Timer_Tick(object sender, EventArgs e) {
if (DateStampCountDownTo != null) {
TimeSpan t = DateStampCountDownTo.Value - TimeProvider.Current.UtcNow;
myTextEdit.MaskType = MaskType.None;
if (t < TimeSpan.Zero) {
myTextEdit.MaskType = MaskType.None;
myTextEdit.EditValue = "Closed";
}
myTextEdit.EditValue = t;
} else {
myTextEdit.EditValue = null;
}
}
}
这是一个复杂的问题(我希望通过使用DevExpress&#39; Textedit控件不会复杂化)。我想知道是否有人给我任何指示我应该去修复它的地方? (或如何解决它)。谢谢大家的时间。
UPDATE1: 我不知道为什么,但是; 此事件处理程序永远不会运行 - &gt; private static void CountDownToChanged(DependencyObj ... 此事件处理程序执行 - &gt; private static void已更改(DependencyObj ...
问题可能在DependencyProperty声明中吗?
UPDATE2: 继续update1之后,我还发现CountDownToChanged事件处理程序使用静态参数输入运行,但在使用bound参数时则不行。
UPDATE3: 我在这里更新了代码以删除datacontext =此代码。并且还纠正了对照的xaml中的相对结合。
仍然存在问题。
UPDATE4: 好。这是工作。经过几个小时的尝试,我真的无法弄清楚我做了什么让它发挥作用。我怀疑Clemens链接副本是答案,我做了某种形式的绑定错误,这掩盖了它确实有效的事实。
由于这个原因,可能值得删除这篇文章,因为我不知道真正的解决方案,我怀疑没有人会发现这个有用。
答案 0 :(得分:0)
您的Entity.MarketDescription.SuspendTime
课程如何?
属性SuspendTime
应实现接口INotifyPropertyChanged
,以便每次更新时通知您的控件。
顺便说一下,我注意到您的工作代码中没有Mode=OneTime
。有什么理由吗?
Here是实施INPC的一个例子
类似的东西:
public class MarketDescription : INotifyPropertyChanged
{
// implements your interface here
...
// your property to bind
private DateTime suspendTime;
public DateTime SuspendTime
{
get { return suspendTime; }
set
{
suspendTime = value;
NotifyPropertyChanged("SuspendTime");
}
}
}