【解決方法】WPFアプリで選択した各アイテムの列に表示される日付と時刻の値を手動で入力する方法は?


こんにちは。
私はこのようなアプリを持っています(https://i.stack.imgur.com/cVUq1.jpg[^])。 ユーザーが DatePicker (DatePick) を使用してインタビューの日付を追加し、Interview Date 列の選択した項目に入力できるようにしてから、最初に[Interview Time]列に「11:115」などの時刻を手動で入力できるようにします。項目 (各行) を選択し、関連するボタンをクリックします。

[![enter image description here][1]][1]

現時点では、Interview Date 列にのみ日付部分を正しく表示して日付を入力します。 ただし、時間を入力すると、面接日が今日の日付 (20/12/2022) に変更されます。

.xaml.cs の私のコード:

C#
    public partial class Shortlist : Window
    {
     
//      list of shortlisted clients
        List<ShortlistedClient> shlclients = new List<ShortlistedClient>();

        public DateTime? SelectedDateFormat { get; private set; }

        // generate dummy data for a shortlist
        public Shortlist()
        {
            InitializeComponent();     
            DataContext = shlclients;
            shlclients.Add(new ShortlistedClient("Rich", "07515118265", "rich@gmail.com", "Glasgow", "Office", "BSc", "more than 3 years", "Yes", "No"));
            shlclients.Add(new ShortlistedClient("Steve", "07515118265", "steve@gmail.com", "Glasgow", "Construction", "High School", "1-3 years", "Yes", "No"));
            shlclients.Add(new ShortlistedClient("Simon", "07485999005", "simon@gmail.com", "Edinburgh", "Office", "MSc", "more than 3 years", "Yes", "No"));
        }


        // method to add date to each selected client
        private void addInterviewDate(object sender, RoutedEventArgs e)
        {
            ShortlistedClient sc = dgr.SelectedItem as ShortlistedClient;

            if (sc != null)
            {
                sc.DT = DatePick.SelectedDate;
            }

        }
        // method to add time to each selected client
        private void addInterviewTime(object sender, RoutedEventArgs e)
        {
            ShortlistedClient sc = dgr.SelectedItem as ShortlistedClient;

             if (sc != null && DateTime.TryParse(textBox.Text, out DateTime result))

            {
                 sc.DT = result;
            }

        }

私の .xaml ウィンドウ コードは次のとおりです。

“`

XML
<Window x:Class="WpfApp_Employment_Help.Shortlist"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp_Employment_Help"
        mc:Ignorable="d"
        Title="Shortlist" Height="450" Width="800">
    <StackPanel Margin="0,0,0,73">
        <DataGrid x:Name="dgr" AutoGenerateColumns="False" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" CanUserAddRows="False" Height="154" Width="793">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                <DataGridTextColumn Header="Email" Binding="{Binding Email}" />
                <DataGridTextColumn Header="Phone" Binding="{Binding Phone}"/>
                <DataGridTextColumn Header="Location" Binding="{Binding Location}"/>
                <DataGridTextColumn Header="Worktype" Binding="{Binding Worktype}"/>
                <DataGridTextColumn Header="Qualification" Binding="{Binding Qualification}"/>
                <DataGridTextColumn Header="Workexp" Binding="{Binding Workexp}"/>
                <DataGridTextColumn Header="Driving licence" Binding="{Binding Drlicence}"/>
                <DataGridTextColumn Header="Criminal conviction" Binding="{Binding Crconviction}"/>
                <DataGridTextColumn Header="Interested in vacancy" Binding="{Binding InterestedinVac}"/>
                <DataGridTemplateColumn Header="Interview Date">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding DT, StringFormat=dd/MM/yyyy}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <DatePicker SelectedDate="{Binding DT, StringFormat=dd/MM/yyyy}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>

                <DataGridTemplateColumn Header="Interview Time">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding DT, StringFormat=HH:mm}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <Button Content="Add Interview Date" Width="128" FontWeight="Bold" Height="28" Click="addInterviewDate"/>
        <DatePicker x:Name="DatePick" Height="52" Width="200"/>
        <Button Content="Add Interview Time" FontWeight="Bold" Click="addInterviewTime" Height="25" Width="116"/>
        <TextBox x:Name="textBox" TextWrapping="Wrap" Width="197" Height="45" Text="Enter time"/>
        <Button x:Name="BtnRemoveShlClient" Content="Remove Shortlisted Client" FontWeight="Bold" Height="33" Width="220" Click="RemoveShClient"/>
    </StackPanel>
</Window>

以前、ShortlistedClient クラスと日時変数は次のように定義されていました。

public class ShortlistedClient : Client, INotifyPropertyChanged
    {
        private DateTime? _dt;

        public DateTime? DT
        {
            get { return _dt; }
            set { _dt = value; NotifyPropertyChanged(); }
        }

        public bool InterestedinVac { get; private set; }


        public List<ShortlistedClient> clients { get; set; } = new List<ShortlistedClient>();
        public ShortlistedClient(string n, string p, string e, string l, string wt, string q, string we, string dl, string cc) : base(n, p, e, l, wt, q, we, dl, cc)
        {
            DT = new DateTime();
            InterestedinVac = true;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }




how can I make it work?  I could make date and time as an entry in one column, but I want them to be in two separate columns.
  [1]: https://i.stack.imgur.com/cVUq1.jpg

私が試したこと:

I have tried to change my line for the time method like this. It does not give me any errors but now it stops taking the time entries.
it looks like the DatePicker dominates both entries because if I dont pick a particular date with the DatePicker, and click the Add Interview Date button, it clears the values for both Interview Date and Interview Time.
<pre lang="C#">```
        private void addInterviewTime(object sender, RoutedEventArgs e)
        {
            ShortlistedClient sc = dgr.SelectedItem as ShortlistedClient;

            if (sc != null && DateTime.TryParseExact(textBox.Text, "HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result))
            {
                 sc.DT = result;
            }

        }

解決策 2

引用:
C#
DateTime.TryParseExact(textBox.Text, "HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result)

それが成功した場合、 result が含まれます DateTime 解析された時間を表す 当日.

次に、 DT その値を持つプロパティ、日付ピッカーで選択された日付を破棄します。

同様に、日付ピッカーで日付を選択すると、 DT プロパティ、解析された時間を破棄します。

日付と時刻を別々に入力する場合は、別々に保存する必要があります。

C#
public class ShortlistedClient : Client, INotifyPropertyChanged
{
    private DateTime? _date;
    private DateTime? _time;
    
    public DateTime? Date
    {
        get { return _date; }
        set 
        {
            _date = value?.Date;
            OnPropertyChanged();
            OnPropertyChanged(nameof(DT));
        }
    }
    
    public DateTime? Time
    {
        get { return _time; }
        set 
        {
            _time = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(DT));
        }
    }
    
    public DateTime? DT
    {
        get
        {
            if (_time is null) return _date;
            if (_date is null) return _time;
            return _date.Value.Date + _time.Value.TimeOfDay;
        }
    }
    
    ...
C#
private void addInterviewDate(object sender, RoutedEventArgs e)
{
    if (dgr.SelectedItem is ShortlistedClient sc)
    {
        sc.Date = DatePick.SelectedDate;
    }
}

private void addInterviewTime(object sender, RoutedEventArgs e)
{
    if (dgr.SelectedItem is ShortlistedClient sc
        && DateTime.TryParseExact(textBox.Text, "HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out DateTime result))
    {
        sc.Time = result;
    }
}
XAML
<DataGridTemplateColumn Header="Interview Date">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Date, StringFormat=dd/MM/yyyy}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <DatePicker SelectedDate="{Binding Date}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

<DataGridTemplateColumn Header="Interview Time">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Time, StringFormat=HH:mm}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

編集: .NET 6 以降を使用している場合は、新しい DateOnlyTimeOnly タイプ:
.NET 6 で DateOnly と TimeOnly を使用する – Steve Gordon – Code with Steve[^]

C#
public class ShortlistedClient : Client, INotifyPropertyChanged
{
    private DateOnly? _date;
    private TimeOnly? _time;
    
    public DateOnly? Date
    {
        get { return _date; }
        set 
        {
            _date = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(DT));
        }
    }
    
    public TimeOnly? Time
    {
        get { return _time; }
        set 
        {
            _time = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(DT));
        }
    }
    
    public DateTime? DT
    {
        get
        {
            if (_time is null) return _date?.ToDateTime(default);
            if (_date is null) return DateTime.Today.Add(_time.Value.ToTimeSpan());
            return _date.Value.ToDateTime(_time.Value);
        }
    }
    
    ...
C#
private void addInterviewDate(object sender, RoutedEventArgs e)
{
    if (dgr.SelectedItem is ShortlistedClient sc)
    {
        sc.Date = DateOnly.FromDateTime(DatePick.SelectedDate);
    }
}

private void addInterviewTime(object sender, RoutedEventArgs e)
{
    if (dgr.SelectedItem is ShortlistedClient sc
        && TimeOnly.TryParseExact(textBox.Text, "HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out TimeOnly result))
    {
        sc.Time = result;
    }
}

コメント

タイトルとURLをコピーしました