我有一個表達式交互性DataTrigger
,它基於約束TimeSpan
屬性更改TextBlock
的Text
屬性。當該值大於或等於Timespan.Zero
時,文本將是該屬性的值。當該值小於零時,該值變爲「??:??:??」。表達式交互性數據觸發器不能正確顯示界限值
相關的代碼如下:
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding InspectionService.TimeRemainingForPart}" Comparison="GreaterThanOrEqual" Value="{x:Static sys:TimeSpan.Zero}">
<ei:ChangePropertyAction PropertyName="Text" Value="{Binding InspectionService.TimeRemainingForPart}" />
</ei:DataTrigger>
<ei:DataTrigger Binding="{Binding InspectionService.TimeRemainingForPart}" Comparison="LessThan" Value="{x:Static sys:TimeSpan.Zero}">
<ei:ChangePropertyAction PropertyName="Text" Value="??:??:??" />
</ei:DataTrigger>
</i:Interaction.Triggers>
的TimeRemainingForPart
屬性經由InspectionService
定時器更新。當定時器運行時,一切都很好。當計時器停止時(將TimeRemainingForPart
設置爲Timespan.Zero),視圖按預期顯示「00:00:00」。但是,應用程序首次加載時,文本塊中不顯示任何內容。我甚至嘗試過改變值/通知從InspectionService
構造函數改變的屬性,並沒有任何反應。
我總是可以通過一個名爲「TimespanLessThanZeroConverter」的轉換器或者其他一些標準的WPF DataTrigger,但是對於爲什麼當前應用程序啓動時無法工作的想法有任何想法?
編輯:忘了提我曾試圖調用OnPropertyChanged的TimeRemainingForPart財產在我的構造函數以防萬一沒有得到正確通知服務,但這似乎並沒有完成任何事情。
編輯2:爲文本塊和ViewModel和服務的相關部分添加完整的XAML。
XAML:
<TextBlock Grid.Row="1" FontSize="56" FontWeight="Bold" Text="{Binding InspectionService.TimeRemainingForPart}">
<TextBlock.Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource StatusIndicatorTextBlockStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding InspectionService.InspectionExecutionState}" Value="{x:Static enum:InspectionExecutionStates.Paused}">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard Duration="0:0:1" AutoReverse="True" RepeatBehavior="Forever">
<ColorAnimation Storyboard.TargetProperty="Foreground.(SolidColorBrush.Color)" To="Transparent" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard Duration="0:0:1">
<ColorAnimation Storyboard.TargetProperty="Foreground.(SolidColorBrush.Color)" To="White" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding InspectionService.TimeRemainingForPart}" Comparison="GreaterThanOrEqual" Value="{x:Static sys:TimeSpan.Zero}">
<ei:ChangePropertyAction PropertyName="Text" Value="{Binding InspectionService.TimeRemainingForPart}" />
</ei:DataTrigger>
<ei:DataTrigger Binding="{Binding InspectionService.TimeRemainingForPart}" Comparison="LessThan" Value="{x:Static sys:TimeSpan.Zero}">
<ei:ChangePropertyAction PropertyName="Text" Value="??:??:??" />
</ei:DataTrigger>
</i:Interaction.Triggers>
</TextBlock>
視圖模型:
public class MyViewModel : IMyViewModel
{
public IInspectionService InspectionService { get; private set; }
public MyViewModel (IInspectionService inspectionService)
{
this.InspectionService = inspectionService;
}
}
服務:
public class InspectionService : BindableBase, IInspectionService
{
private readonly IModeService _modeService;
private readonly IRemainingTimeFileServiceFactory _remainingTimeFileServiceFactory;
private string _inspectionCell;
private readonly DispatcherTimer _timeRemainingForPartTimer;
#region IInspectionService Members
private InspectionExecutionStates _inspectionExecutionState;
public InspectionExecutionStates InspectionExecutionState
{
get { return this._inspectionExecutionState; }
private set { this.SetProperty(ref this._inspectionExecutionState, value); }
private string _inspectionName;
public string InspectionName
{
get { return this._inspectionName; }
private set { this.SetProperty(ref this._inspectionName, value); }
}
private TimeSpan _timeRemainingForPart;
public TimeSpan TimeRemainingForPart
{
get { return this._timeRemainingForPart; }
private set { this.SetProperty(ref this._timeRemainingForPart, value); }
private TimeSpan _totalTimeRemaining;
public TimeSpan TotalTimeRemaining
{
get { return this._totalTimeRemaining; }
private set { this.SetProperty(ref this._totalTimeRemaining, value); }
}
#endregion
public InspectionService(IModeService modeService, IRemainingTimeFileServiceFactory remainingTimeFileServiceFactory)
{
this._modeService = modeService;
this._remainingTimeFileServiceFactory = remainingTimeFileServiceFactory;
this._timeRemainingForPartTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
this._timeRemainingForPartTimer.Tick += this.TimeRemainingForPartTimerOnTick;
}
private void StartSelectedInspection(InspectionPlanInfo inspectionPlanInfo)
{
this.SetInspectionProperties(inspectionPlanInfo);
this.StartInspection
}
#endregion
#region Private Methods
private void StartInspection()
{
this.TotalTimeRemaining = this._remainingTimeFileServiceFactory.GetIRemainingTimeFileService(this._inspectionCell).GetInspectionTime(this.InspectionName);
this.TimeRemainingForPart = this._modeService.IsStudyActive ? TimeSpan.MinValue : this.TotalTimeRemaining;
this._timeRemainingForPartTimer.Start();
}
private void StopInspection()
{
this.ClearInspectionProperties();
this._timeRemainingForPartTimer.Stop();
}
private void SetInspectionProperties(InspectionPlanInfo inspectionPlanInfo)
{
this.InspectionName = inspectionPlanInfo.InspectionName;
this._inspectionCell = inspectionPlanInfo.Cell;
}
private void ClearInspectionProperties()
{
this.InspectionName = "";
this.TimeRemainingForPart = TimeSpan.Zero;
this.TotalTimeRemaining = TimeSpan.Zero;
}
private void TimeRemainingForPartTimerOnTick(object sender, EventArgs eventArgs)
{
if (this.TimeRemainingForPart < TimeSpan.Zero)
{
this._timeRemainingForPartTimer.Stop();
}
else
{
this.TimeRemainingForPart -= TimeSpan.FromSeconds(1);
this.TotalTimeRemaining -= TimeSpan.FromSeconds(1);
}
}
}
編輯3:
那麼顯然它不能沒有轉換器這樣做TextBlock代碼是mo dified如下:
<TextBlock Grid.Row="1" FontSize="56" FontWeight="Bold">
<TextBlock.Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource StatusIndicatorTextBlockStyle}">
<Setter Property="Text" Value="{Binding InspectionService.TimeRemainingForPart}" />
<Style.Triggers>
<DataTrigger Binding="{Binding InspectionService.TimeRemainingForPart, Converter={StaticResource TimespanLessThanZeroConverter}}"
Value="True">
<Setter Property="Text" Value="??:??:??" />
</DataTrigger>
<DataTrigger Binding="{Binding InspectionService.InspectionExecutionState}" Value="{x:Static enum:InspectionExecutionStates.Paused}">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard Duration="0:0:1" AutoReverse="True" RepeatBehavior="Forever">
<ColorAnimation Storyboard.TargetProperty="Foreground.(SolidColorBrush.Color)" To="Transparent" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard Duration="0:0:1">
<ColorAnimation Storyboard.TargetProperty="Foreground.(SolidColorBrush.Color)" To="White" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
而對於完整性/子孫後代着想轉換器看起來是這樣的:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace CurrentInspection.Converters
{
public class TimespanLessThanZeroConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is TimeSpan))
{
return false;
}
return (TimeSpan)value < TimeSpan.Zero;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
}
設置爲默認會發生在服務的構造函數中,實際上(它繼承了Prism中的'BindableBase')。但我已經嘗試從構造函數中調用OnPropertyChanged,認爲它可以工作,但事實並非如此。 (我應該更新我的問題,以表明我嘗試了這個。) – GrantA
請包括TextBlock和您的視圖模型的完整標記。 – mm8
我按要求添加了附加代碼。 – GrantA