仅绑定日期和仅时间

Posted

技术标签:

【中文标题】仅绑定日期和仅时间【英文标题】:Binding Date Only and Time Only 【发布时间】:2017-06-16 19:00:10 【问题描述】:

我有 2 个控件:

DatePicker:仅用于日期 带有 TimeMask 的文本框:仅限时间

它们都链接到同一个属性DateTime EffectiveDate 但问题是当我更改 DatePicker 上的日期时,它会将 TimeTextBox 中的时间更改回 12:00。

我理解它的原因,但有什么最佳解决方案可以让这些单独工作但绑定到同一个属性?

我试图获取当前时间并在 set 属性中构建一个新日期,但总是以溢出错误结束。

【问题讨论】:

为什么没有两个属性 EffectiveDate 和 EffectiveTime,它们都在模型中使用相同的支持字段。 嗯,好的,我会回到那个 - 但那里也有溢出错误 【参考方案1】:

您可以使用价值转换器来保持价值

public class DateConverter : IValueConverter

    private DateTime timePickerDate;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    
        timePickerDate = ((DateTime)(value));

        return value;
    

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    
        if (value == null) return timePickerDate;

        var datePickerDate = ((DateTime)(value));

        // compare relevant parts manually
        if (datePickerDate.Hour != timePickerDate.Hour
            || datePickerDate.Minute != timePickerDate.Minute
            || datePickerDate.Second != timePickerDate.Second)
        
            // correct the date picker value
            var result = new DateTime(datePickerDate.Year,
                 datePickerDate.Month,
                 datePickerDate.Day,
                 timePickerDate.Hour,
                 timePickerDate.Minute,
                 timePickerDate.Second);

            // return, because this event handler will be executed a second time
            return result;
        

        return datePickerDate;
    

并让有问题的两个控件绑定到一个属性,但让日期选择器使用转换器不覆盖时间。

<Grid Margin="10,5" >        
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition Width="auto"/>
    </Grid.ColumnDefinitions>
    <sdk:DatePicker Grid.Column="0" TabIndex="1" Padding="0" SelectedDate="Binding EffectiveDate, Mode=TwoWay, Converter=StaticResource DateConverter" SelectedDateFormat="Short"/>
    <toolkit:TimePicker Grid.Column="1" Value="Binding EffectiveDate, Mode=TwoWay" Margin="0" Padding="0" HorizontalAlignment="Left" TabIndex="2" />
</Grid>

【讨论】:

正是我需要的,甚至不需要摆弄 objects 属性。谢谢一百万。 好的,发现一个问题。假设我选择了 21/01/2017,时间是 12:00。在我更改时间的那一刻,日期跳回到今天 (31/01/2017)。我是否还需要一个转换器来保持日期不变? 没有。您是否在该属性上更改了正确的通知属性?我会快速新建一个项目,看看能否重现。 @user1702369 按描述工作。当更新的时间和日期仍然存在多次更改时,我通过选择器更改了日期。 我当时正在使用带有 Mask 的扩展 TextBox。你用的是什么时间选择器【参考方案2】:

你可以这样做:

private DateTime _effectiveDate;
...
public DateTime DateOfEffectiveDate

    get  return _effectiveDate; 
    set
    
        _effectiveDate = new DateTime(value.Year, value.Month, value.Day, _effectiveDate.Hour, _effectiveDate.Minute, _effectiveDate.Second);
    


public DateTime TimeOfEffectiveDate

    get  return _effectiveDate; 
    set
    
        _effectiveDate = new DateTime(_effectiveDate.Year, _effectiveDate.Month, _effectiveDate.Day, value.Hour, value.Minute, value.Second);
    

【讨论】:

【参考方案3】:

内置的 DatePicker 控件只选择一个没有任何特定时间的日期,所以我担心尝试在 TextBox 中显示所选日期的时间是没有意义的。每次选择新日期时,DatePicker 都会有效地清除时间部分。这就是控件的工作原理。

因此,您应该将 DatePicker 和 TextBox 绑定到两个不同的源属性,分别是 DateTime?TimeSpan

另一种选择是使用另一个选择日期和时间的控件,例如:http://wpftoolkit.codeplex.com/wikipage?title=DateTimePicker

【讨论】:

【参考方案4】:

捕捉dateTimePicker1_ValueChanged 事件,然后结合datetime 部分设置binded field value

private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
        
            DateTime dt = dateTimePicker1.Value;

            int hour = Convert.ToInt32(textBox1.Text.Split(':')[0]);
            int minute = Convert.ToInt32(textBox1.Text.Split(':')[1]);

            bindedfield = new DateTime(dt.Year, dt.Month, dt.Day, hour, minute, 0);
        

【讨论】:

以上是关于仅绑定日期和仅时间的主要内容,如果未能解决你的问题,请参考以下文章

如何仅使用@DateTimeFormat 将日期@ConfigurationProperties 与时间绑定?

SQL Server:如何在总行数和仅包含数据的行数之间得到差异

日历绑定 SelectedDate 和 DisplayDate:灰色日期

为啥 std::optional 不允许“移动构造和仅复制分配”类型的移动分配?

数组接收的 MPI 和仅适用于一级

RODBC:为啥 sqlQuery() 中的空值和仅空格值的值为“NA”?