WPF DataGrid предварительно редактирует значение ячейки по умолчанию при редактировании. - PullRequest
1 голос
/ 25 июня 2019

У меня очень упрощенная (частично) привязанная к данным ViewModel, которая предоставляет свойство Nullable, которое позже отображается в DataGrid:

public class MyViewModel : ViewModelBase
{
   private DateTime? _date;
   public DateTime? Date {
     get => _date;
     set => Set(ref _date, value);
   }
}

<DataGrid ItemsSource="{Binding MyViewModels}">
   <DataGrid.Columns>
      <DataGridTextColumn Header="Date" Binding="{Binding Date}"/>
   </DataGrid.Columns>
</DataGrid>

Все работает как положено, отображаются даты, у которых есть значение, ячейки для значений null полностью пустые.
Однако как я могу предварительно заполнить привязанные значения null с помощью DateTime.Now при входе в режим редактирования ячейки ? Бонусный пункт: DateTime.Now возвращается к null в случае, если редактирование ячейки было прервано.


Попытка 2 (на основе комментариев) с использованием DataGridTemplateColumn и swich TextBlock без TargetNullValue для TextBox с одним, к сожалению, это недопустимая привязка:

TargetNullValue «25.06.2009 0:00:00» (тип «DateTime») не может быть преобразован для использования в «Текст»

<DataGridTemplateColumn SortMemberPath="Date" Header="Date">
   <DataGridTemplateColumn.CellTemplate>
      <DataTemplate>
         <TextBlock Text="{Binding Date}"/>
      </DataTemplate>
   </DataGridTemplateColumn.CellTemplate>
   <DataGridTemplateColumn.CellEditingTemplate>
      <DataTemplate>
         <TextBox Text="{Binding Date, TargetNullValue={x:Static sys:DateTime.Today}}"/>
      </DataTemplate>                            
   </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

Ответы [ 2 ]

3 голосов
/ 25 июня 2019

Вы можете использовать свойство TargetNullValue, если привязываетесь к свойству SelectedDate невидимого DatePicker:

<DataGridTemplateColumn SortMemberPath="Date" Header="Date">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Date}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <StackPanel>
                <DatePicker x:Name="dp" SelectedDate="{Binding Date, TargetNullValue={x:Static sys:DateTime.Today}}" Visibility="Collapsed" />
                <TextBox Text="{Binding Text, ElementName=dp}" />
            </StackPanel>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

Другим вариантом будет реализация преобразователя значения , который преобразует DateTime.Today в string.

Спасибо за ответ, это гораздо проще, плюс он допускает нестатические значения.Тем не менее, невозможно принять предварительно заполненный DateTime.Today, если пользователь не изменит его на другую дату и обратно ...

Если вы хотите сохранить значение, вы должны установить источниксвойство явно.Вы можете сделать это, обработав событие CellEditEnding.Как то так:

private void Dgm_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    ContentPresenter cp = e.EditingElement as ContentPresenter;
    if (cp != null)
    {
        Panel panel = VisualTreeHelper.GetChild(cp, 0) as Panel;
        if (panel != null)
        {
            TextBox tb = panel.Children.OfType<TextBox>().FirstOrDefault();
            if (tb != null)
            {
                DateTime dt;
                if (DateTime.TryParse(tb.Text, out dt))
                {
                    e.Row.DataContext.GetType().GetProperty("Date").SetValue(e.Row.DataContext, dt);
                }
            }
        }
    }
}
1 голос
/ 25 июня 2019

Вы можете использовать MultiDataTrigger и записать условия, если дата равна нулю и текстовое поле сфокусировано, мы можем установить значение DateTime.now

DataGridTemplateColumn

 <DataGrid Name="drg" AutoGenerateColumns="False"  CanUserAddRows="False" >
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Date" >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox  BorderThickness="0" >
                                <TextBox.Style>
                                    <Style TargetType="TextBox">
                                        <Style.Resources>
                                            <Converter:DateTimeNullConverter x:Key="Time"/>
                                        </Style.Resources>
                                        <Setter Property="Text" Value="{Binding Date}"></Setter>

                                        <Style.Triggers>
                                            <MultiDataTrigger>
                                                <MultiDataTrigger.Conditions>
                                                    <Condition Binding="{Binding Date}" Value="{x:Null}" />
                                                    <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsKeyboardFocused}" Value="True" />
                                                </MultiDataTrigger.Conditions>
                                                <Setter Property="Text" Value="{Binding Date,Converter={StaticResource Time}}"></Setter>
                                            </MultiDataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </TextBox.Style>

                            </TextBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

Преобразователь

Класс DateTimeNullConverter: IValueConverter {

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return DateTime.Now;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...