WPF编辑日期时间的小时和分钟

WPF编辑日期时间的小时和分钟,wpf,datetime,hour,minute,Wpf,Datetime,Hour,Minute,我有3个文本框来编辑日期时间。 需要注意的是,这两个文本框正在编辑第一个文本框DateTime值的小时和分钟。 一个用于编辑日期,两个用于编辑小时和分钟。 你会怎么做?下面的代码在编辑小时或分钟时不反映日期时间的更改,因为它会更改字符串(“HH”),并且日期时间值丢失: <TextBox Text="{Binding MyDateTime}" /> <!--This cannot work : it's just for clearing purposes --&

我有3个文本框来编辑日期时间。 需要注意的是,这两个文本框正在编辑第一个文本框DateTime值的小时和分钟。 一个用于编辑日期,两个用于编辑小时和分钟。 你会怎么做?下面的代码在编辑小时或分钟时不反映日期时间的更改,因为它会更改字符串(“HH”),并且日期时间值丢失:

 <TextBox Text="{Binding MyDateTime}"  />

    <!--This cannot work : it's just for clearing purposes -->
    <TextBox Text="{Binding MyDateTime, StringFormat=\{0:HH\}}}"  />
    <TextBox Text="{Binding MyDateTime}, StringFormat=\{0:mm\}}"  />

当然,我可以使用ViewModel作为DataContext,在这里我可以通过编程方式解决它。
但是我只是想知道,在XAML中是否有直接的可能性,您需要使用一个具有双向绑定的转换器和一个转换器参数。将原始小时保存在转换器中。然后可以适当地更新绑定源。

仅使用XAML是不容易的。如何解决这个问题有几种可能:

1。编写可执行此操作的自定义控件或用户控件

您可以创建一个自定义控件/用户控件(例如DateTimeTextBox),该控件具有xaml可以绑定的属性
日期时间值
,并且包含转换为在两个文本框之一中输入的日期时间值的逻辑。除了两个文本框,您还可以使用类似maskedtextbox的内容

2。ViewModel中的两个专用属性

如果使用MVVM,您可以为ViewModel提供两个专用属性
int-DateTimeHours
int-DateTimeMinutes
,并与之绑定:

<TextBox Text="{Binding MyDateTimeHours}"  />
<TextBox Text="{Binding MyDateTimeMinutes}"  />


然后,您的ViewModel会将这两个属性合并为一个DateTime值。

我很感激这是一篇老文章,但我今天遇到了这个问题,并找到了另一种处理日期和时间绑定的方法

我创建了一个名为dateTime的分部类,它有4个属性,一个用于日期,一个用于小时,另一个用于分钟。然后是返回完成日期的只读dateTime属性

    Partial Public Class dateTimeValue
        Property Dt As Date
        Property Hr As Integer
        Property Mn As Integer

        ReadOnly Property dateTime As Date
            Get
                Dim d = Dt
                d = d.AddHours(d.Hour * -1).AddHours(Hr)
                d = d.AddMinutes(d.Minute * -1).AddMinutes(Mn)
                d = d.AddSeconds(d.Second * -1)
                Return d
            End Get
        End Property
    End Class
然后在XAML中,我使用了一个网格布局,绑定到一个DateTimePicker和几个组合框

            <UniformGrid Columns="2">
                <TextBlock Text="Date"/>
                <DatePicker SelectedDate="{Binding dateTime.Dt}"/>
                <TextBlock Text="Time"/>
                <WrapPanel>
                    <ComboBox SelectedValue="{Binding dateTime.Hr}" SelectedValuePath="Content">
                        <ComboBoxItem>00</ComboBoxItem>
                        <ComboBoxItem>01</ComboBoxItem>
                        <ComboBoxItem>02</ComboBoxItem>
                        .........
                        <ComboBoxItem>22</ComboBoxItem>
                        <ComboBoxItem>23</ComboBoxItem>
                    </ComboBox>
                    <TextBlock Text=":"/>
                    <ComboBox SelectedValue="{Binding dateTime.Mn}" SelectedValuePath="Content">
                        <ComboBoxItem>00</ComboBoxItem>
                        <ComboBoxItem>15</ComboBoxItem>
                        <ComboBoxItem>30</ComboBoxItem>
                        <ComboBoxItem>45</ComboBoxItem>
                    </ComboBox>
                </WrapPanel>
                <Button Click="saveTask" Content="Save Task"/>
            </UniformGrid>

00
01
02
.........
22
23
00
15
30
45
然后在文本块中显示正确的日期和时间

<TextBlock Text="{Binding dateTime.dateTime, StringFormat={}{0:dd MMM yyyy - HH:mm}}"/>

希望这对其他人有所帮助。

100%MVVM

public class DateTimeConverter : IValueConverter
{
    private DateTime _target = DateTime.Now;
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var source = value as DateTime?;
        if (source is null) return null;
        _target = source.Value;
        switch (parameter as string)
        {
            case "y": return source.Value.Year;
            case "m": return source.Value.Month;
            case "d": return source.Value.Day;
            case "h": return source.Value.Hour;
            case "i": return source.Value.Minute;
            default: return null;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        switch (parameter as string)
        {
            case "y": return new DateTime(System.Convert.ToInt32(value), _target.Month, _target.Day, _target.Hour, _target.Minute, 0);
            case "m": return new DateTime(_target.Year, System.Convert.ToInt32(value), _target.Day, _target.Hour, _target.Minute, 0);
            case "d": return new DateTime(_target.Year, _target.Month, System.Convert.ToInt32(value), _target.Hour, _target.Minute, 0);
            case "h": return new DateTime(_target.Year, _target.Month, _target.Day, System.Convert.ToInt32(value), _target.Minute, 0);
            case "i": return new DateTime(_target.Year, _target.Month, _target.Day, _target.Hour, System.Convert.ToInt32(value), 0);
            default: return _target;
        }
    }
}

好。。如果这是真的,我想看一个转换器的例子。ConverteBack:您只有一个字符串值(比如“16”),如何从中获取整个日期?这是行不通的,因为您无法访问当前日期时间值(作为一个整体),因此无法将小时/分钟与之合并。您也不会在转换器中保存任何状态,因为同一个实例可以多次使用。请创建一个包含文本框的用户控件,并按此方式保存它?让我们讨论3:问题是我无法将其与实际日期时间合并,因为这些小时和分钟是第一个日期时间的一部分!所以我需要向ConvertBack方法提供最近的DateTime。是的,你是对的,这不容易做到。我删除了那个想法。。你知道。。在我看来,有些问题没有MVVM是无法克服的。MVVM使很多事情变得更容易。一个人不能陷入MVVM上设想的隧道中。虽然这段代码可能会解决这个问题,但如何以及为什么解决这个问题会真正有助于提高你的文章质量,并可能导致更多的投票。请记住,你是在将来回答读者的问题,而不仅仅是现在提问的人。请在回答中添加解释,并说明适用的限制和假设。