【问题标题】:Format value inside list格式化列表内的值
【发布时间】:2020-11-06 04:17:22
【问题描述】:

我有一个这样的模型:

   public class MyViewModel
    {
        public TimeSpan AverageLogOn { get; set; }
        public TimeSpan AverageLogOff { get; set; }
        public TimeSpan AverageTotalHours { get; set; }
        
    }

我将此模型用作列表,例如:

  public IList<MyViewModel> MyViewModelList { get; set; } = new List<MyViewModel>();

我想做的是将AverageLogOn 格式化为“hh:mm:ss” 我该如何使用LINQ,我想是这样的:

 MyViewModel.Select(x => new MyViewModel { AverageLogOn = x.AverageLogOn.ToString("hh:mm:ss"), AverageLogOff = x.AverageLogOff, AverageTotalHours = x.AverageTotalHours });

但是当我尝试x.AverageLogOn.ToString("hh:mm:ss") 时,它会抛出一个错误

无法将类型“字符串”隐式转换为“System.TimeSpan”

我做错了什么?问候

【问题讨论】:

  • ToString 创建一个字符串,目标类型为 TimeSpan。您要么需要分配时间跨度,而不是字符串,要么需要将目标类型更改为字符串。
  • 此外,TimeSpan 没有 格式——当你想显示它时你可以指定一个格式。您应该在那里指定格式,而不是在 ViewModel 中。

标签: c# linq


【解决方案1】:

我做错了什么?

您正在尝试将 string 分配给需要 TimeSpan 值的属性。就像错误消息说的那样。基本上和这个问题一样:How to convert time to 24Hr format from DateTime.Now.

您没有提供太多上下文,因此不清楚您希望如何使用 Select() 调用的结果。 可能是在 string 值实际上对这些属性有意义的上下文中。如果是这样,那么您可以从代码中删除 MyViewModel 并创建一个匿名类型:

MyViewModelList.Select(x => new { AverageLogOn = x.AverageLogOn.ToString("hh:mm:ss"), AverageLogOff = x.AverageLogOff, AverageTotalHours = x.AverageTotalHours });

您将获得对象的枚举,其类型未命名(即“匿名”),并且不同于您原来的 MyViewModel 对象类型,其中 AverageLogOn 属性现在类型为 string 而不是 TimeSpan。但是请注意,匿名类型的使用方式存在限制。但是,由于 WPF 在 XAML 中执行所有操作而没有太多类型安全性,因此完全有可能完全按照您的意愿行事。

注意:您没有在帖子中显示您如何实际使用调用Select() 的结果。但我想确保您了解Select() 不会对原始集合做任何事情。它不会修改MyViewModelList。 Select() 方法在这里返回一个IEnumerable&lt;MyViewModel&gt; 的实例,您必须以某种方式使用该引用才能真正看到Select() 所做的工作。 (事实上​​,在您真正“实现”该枚举,即以某种方式枚举值序列之前,实际上什么都没有发生,甚至匿名类型对象的实例化也没有。)

另一方面,也许您真正需要的只是调整您的 XAML 以按照您想要的方式格式化 TimeSpan 值。在这种情况下,您根本不需要 Select() 方法。相反,您需要在绑定标记中包含 StringFormat 说明符,如下所示:

<TextBox Text="{Binding AverageLogOn, StringFormat={}{0:hh}:{0:mm}}" />

有关更多信息,请参阅此问题:How to format converter paramter in wpf。

错误本身的原因很明显,错误信息看起来也很清楚。由于缺乏更多关于您为什么会首先陷入这种情况的详细信息,因此很难确定您的问题的实际答案应该是什么。我认为以上内容应该足以解决您的问题,但如果这些建议不能解决您的问题,请edit your question 进行改进,以便清楚您要做什么。

【讨论】:

    【解决方案2】:

    尝试使用扩展方法,记住天可以超过 24 天

    public static class MyExtensions
    {
        public static string ToCustomString(this TimeSpan span)
        {
            return string.Format("{0:00}:{1:00}:{2:00}", span.Hours, span.Minutes, span.Seconds);
        }
    }
    

    然后你会打电话

    x.AverageLogOn.ToCustomString()
    

    你也可以打电话

    x.AverageLogOn.ToString(@"hh\:mm\:ss");
    

    再一次,你会错过这些日子

    更新感谢大卫: 我错过了转换错误,您可以使用返回时间跨度的语句解析字符串,如果失败则返回“零”时间跨度

    TryParse(string,out var time)?时间:Timespan.FromSeconds(0)

    看看online documentation

    【讨论】:

    • 这实际上并不能解决问题,因为 OP 仍会将字符串分配给 TimeSpan。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 2013-08-06
    • 1970-01-01
    相关资源
    最近更新 更多