转换器和枚举以更改 TextBlock 的前景色
Converter and enum to change Foreground color of TextBlock
我想以特定格式在 TextBlock
我的变量 TrainDelay
中显示
我使用转换器 IntToTimeSpanConverter
来格式化 TrainDelay : (mm:ss)
所以根据TrainDelay的值如:
- 以红色显示
Delayed (00:23)
- 以深色显示
On Time (00:00)
- 以绿色显示
In Advance (- 00:15)
一些代码:
public class TimeSpanFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int.TryParse(value.ToString(), out int time);
value = TimeSpan.FromSeconds(time);
if (string.IsNullOrWhiteSpace(value.ToString()) || ((TimeSpan)value).Equals(TimeSpan.MinValue))
return "––:––";
else if(time > 0)
{
return TrainDelay.Delayed + " " + ((((TimeSpan)value) < TimeSpan.Zero) ? "-" : "") + ((TimeSpan)value).ToString(@"mm\:ss");
}
else if (time < 0)
{
return TrainDelay.InAdvance + " " + ((((TimeSpan)value) < TimeSpan.Zero) ? "-" : "") + ((TimeSpan)value).ToString(@"mm\:ss");
}
else
{
return TrainDelay.OnTime + " " + ((((TimeSpan)value) < TimeSpan.Zero) ? "-" : "") + ((TimeSpan)value).ToString(@"mm\:ss");
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public enum TrainDelay
{
OnTime,
Delayed,
InAdvance
}
我在这个 XAML 中使用 DataTrigger
尝试过这个:
<TextBlock Name="tb" >
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="defaultDelay"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=tb, Path=TrainDelay, Converter={StaticResource TimeSpanFormatConverter}}" Value="Delayed">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Text" Value="{Binding TrainDelay, Converter={StaticResource TimeSpanFormatConverter}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
我仍然没有得到正确的结果!
我是 C# WPF 编程的初学者,我需要帮助来实现这个或者可能有更多的解释来真正理解这个问题
此绑定的作用是查找名为 tb
的元素,然后在该元素上查找名为 TrainDelay
的 属性。就在那里它失败了,因为 TextBlock 没有那个名字的 属性。 TrainDelay
是视图模型的 属性,而不是控件的。
<DataTrigger
Binding="{Binding ElementName=tb, Path=TrainDelay, Converter={StaticResource TimeSpanFormatConverter}}"
Value="Delayed">
如果您想在火车的 "delayedness" 上触发,您需要另一个转换器将 TrainDelay
属性 转换为枚举。将 "Delayed" 与格式化的时间字符串进行比较将永远行不通。
那个新的转换器看起来像这样。它只是另一个的简化版本。当我这样做时,我将重写您的转换器以简化它并删除大量冗余代码。冗余代码是个坏主意:起初,它只是混乱。一年后有人来维护这个东西,他们浪费了一些时间来确认这三个子表达式确实完全相同。明年其他人会改变其中两个。一年后,有人需要进行另一项更改,并错误地认为第三项 应该 有所不同。与此同时,其他人复制并粘贴了整个乱七八糟的东西,现在你遇到了更多问题。
public class TimeToDelayConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int.TryParse(value.ToString(), out int time);
var span = TimeSpan.FromSeconds(time);
if (string.IsNullOrWhiteSpace(value.ToString()) || span.Equals(TimeSpan.MinValue))
{
return null;
}
else
{
return TimeSpanFormatConverter.SecondsToDelay(time);
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class TimeSpanFormatConverter : IValueConverter
{
public static TrainDelay SecondsToDelay(int time)
{
if (time > 0)
{
return TrainDelay.Delayed;
}
else if (time < 0)
{
return TrainDelay.InAdvance;
}
else
{
return TrainDelay.OnTime;
}
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int.TryParse(value.ToString(), out int time);
// Don't assign this back to value. Assign it to a new variable that's properly
// typed, so you don't need to cast it.
var span = TimeSpan.FromSeconds(time);
if (string.IsNullOrWhiteSpace(value.ToString()) || span.Equals(TimeSpan.MinValue))
{
return "––:––";
}
else
{
// No need to copy and paste the same code three times.
var timeStr = ((span < TimeSpan.Zero) ? "-" : "") + span.ToString(@"mm\:ss");
return $"{SecondsToDelay(time)} {timeStr}";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public enum TrainDelay
{
OnTime,
Delayed,
InAdvance
}
然后你的触发器看起来像这样。请注意,它使用的转换器与以前不同。
<DataTrigger
Binding="{Binding TrainDelay, Converter={StaticResource TimeToDelayConverter}}"
Value="Delayed">
我想以特定格式在 TextBlock
我的变量 TrainDelay
中显示
我使用转换器 IntToTimeSpanConverter
来格式化 TrainDelay : (mm:ss)
所以根据TrainDelay的值如:
- 以红色显示
Delayed (00:23)
- 以深色显示
On Time (00:00)
- 以绿色显示
In Advance (- 00:15)
一些代码:
public class TimeSpanFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int.TryParse(value.ToString(), out int time);
value = TimeSpan.FromSeconds(time);
if (string.IsNullOrWhiteSpace(value.ToString()) || ((TimeSpan)value).Equals(TimeSpan.MinValue))
return "––:––";
else if(time > 0)
{
return TrainDelay.Delayed + " " + ((((TimeSpan)value) < TimeSpan.Zero) ? "-" : "") + ((TimeSpan)value).ToString(@"mm\:ss");
}
else if (time < 0)
{
return TrainDelay.InAdvance + " " + ((((TimeSpan)value) < TimeSpan.Zero) ? "-" : "") + ((TimeSpan)value).ToString(@"mm\:ss");
}
else
{
return TrainDelay.OnTime + " " + ((((TimeSpan)value) < TimeSpan.Zero) ? "-" : "") + ((TimeSpan)value).ToString(@"mm\:ss");
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public enum TrainDelay
{
OnTime,
Delayed,
InAdvance
}
我在这个 XAML 中使用 DataTrigger
尝试过这个:
<TextBlock Name="tb" >
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="defaultDelay"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=tb, Path=TrainDelay, Converter={StaticResource TimeSpanFormatConverter}}" Value="Delayed">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Text" Value="{Binding TrainDelay, Converter={StaticResource TimeSpanFormatConverter}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
我仍然没有得到正确的结果!
我是 C# WPF 编程的初学者,我需要帮助来实现这个或者可能有更多的解释来真正理解这个问题
此绑定的作用是查找名为 tb
的元素,然后在该元素上查找名为 TrainDelay
的 属性。就在那里它失败了,因为 TextBlock 没有那个名字的 属性。 TrainDelay
是视图模型的 属性,而不是控件的。
<DataTrigger
Binding="{Binding ElementName=tb, Path=TrainDelay, Converter={StaticResource TimeSpanFormatConverter}}"
Value="Delayed">
如果您想在火车的 "delayedness" 上触发,您需要另一个转换器将 TrainDelay
属性 转换为枚举。将 "Delayed" 与格式化的时间字符串进行比较将永远行不通。
那个新的转换器看起来像这样。它只是另一个的简化版本。当我这样做时,我将重写您的转换器以简化它并删除大量冗余代码。冗余代码是个坏主意:起初,它只是混乱。一年后有人来维护这个东西,他们浪费了一些时间来确认这三个子表达式确实完全相同。明年其他人会改变其中两个。一年后,有人需要进行另一项更改,并错误地认为第三项 应该 有所不同。与此同时,其他人复制并粘贴了整个乱七八糟的东西,现在你遇到了更多问题。
public class TimeToDelayConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int.TryParse(value.ToString(), out int time);
var span = TimeSpan.FromSeconds(time);
if (string.IsNullOrWhiteSpace(value.ToString()) || span.Equals(TimeSpan.MinValue))
{
return null;
}
else
{
return TimeSpanFormatConverter.SecondsToDelay(time);
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class TimeSpanFormatConverter : IValueConverter
{
public static TrainDelay SecondsToDelay(int time)
{
if (time > 0)
{
return TrainDelay.Delayed;
}
else if (time < 0)
{
return TrainDelay.InAdvance;
}
else
{
return TrainDelay.OnTime;
}
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int.TryParse(value.ToString(), out int time);
// Don't assign this back to value. Assign it to a new variable that's properly
// typed, so you don't need to cast it.
var span = TimeSpan.FromSeconds(time);
if (string.IsNullOrWhiteSpace(value.ToString()) || span.Equals(TimeSpan.MinValue))
{
return "––:––";
}
else
{
// No need to copy and paste the same code three times.
var timeStr = ((span < TimeSpan.Zero) ? "-" : "") + span.ToString(@"mm\:ss");
return $"{SecondsToDelay(time)} {timeStr}";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public enum TrainDelay
{
OnTime,
Delayed,
InAdvance
}
然后你的触发器看起来像这样。请注意,它使用的转换器与以前不同。
<DataTrigger
Binding="{Binding TrainDelay, Converter={StaticResource TimeToDelayConverter}}"
Value="Delayed">