简体   繁体   English

WPF DataGrid在编辑时预填充单元格默认值

[英]WPF DataGrid prefill a Cell default value on edit

I have very simlistic (partof) data-bound ViewModel that exposes a Nullable property, which is later rendered in a DataGrid : 我有一个非常简单的(部分)数据绑定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>

Everything works as expected, Dates which has a value are displayed, cells for null values are completely blank. 一切正常,显示有值的日期, null值的单元格完全空白。
However, how can I prefill bound null values with DateTime.Now when entering cell edit mode ? 但是, 当进入单元格编辑模式时 ,如何用DateTime.Now预填充绑定的null值? Bonus point: the DateTime.Now is reverted back to null in case cell edit was aborted. 奖励点:万一单元格编辑被中止, DateTime.Now将还原为null


Attempt 2 (based on comments), using DataGridTemplateColumn and swich TextBlock without TargetNullValue for a TextBox with one, sadly that is not a valid binding: 尝试2 (基于注释),对不带TargetNullValueTextBox使用DataGridTemplateColumn和swich TextBlock进行TargetNullValue ,但不幸的是这不是有效的绑定:

TargetNullValue '6/25/2019 0:00:00' (type 'DateTime') cannot be converted for use in 'Text' 无法转换TargetNullValue'6/25/2019 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>

You could use the TargetNullValue property if you bind to the SelectedDate property of an invisible DatePicker : 如果绑定到不可见的DatePickerSelectedDate属性,则可以使用TargetNullValue属性:

<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>

The other option would be to implement a value converter that converts DateTime.Today to a string . 另一个选择是实现一个将DateTime.Today转换为string值转换器

Thanks for the answer, its definitely much simpler plus it allows non-static values. 感谢您的回答,它肯定简单得多,并且允许使用非静态值。 However, it is not possible to accept the pre-filled DateTime.Today unless user changes it to a different date and back ... 但是,除非用户将其更改为其他日期然后返回...,否则无法接受预先填写的DateTime.Today。

If you want to persist the value, you should set the source property explicitly. 如果要保留该值,则应显式设置source属性。 You could do this by handling the CellEditEnding event. 您可以通过处理CellEditEnding事件来做到这一点。 Something like this: 像这样:

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);
                }
            }
        }
    }
}

You can use a MultiDataTrigger and write the conditions if the date is equal to null and the textbox is focused we can set the value to DateTime.now 您可以使用MultiDataTrigger并编写条件(如果日期等于null且文本框已聚焦),我们可以将值设置为DateTime.now

DataGridTemplateColumn 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>

Convertor 转换器

class DateTimeNullConverter : IValueConverter { class 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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM