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

我有 2 个控件:

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

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

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

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

【问题讨论】:

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

标签: c# wpf mvvm data-binding datepicker


【解决方案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);
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-25
        • 2015-10-30
        相关资源
        最近更新 更多