DateTime Editor in WPF property grid

Grids for WPF Forum

Posted 3 years ago by Bruce Lum
Version: 16.1.0630
Platform: .NET 4.0
Environment: Windows 7 (64-bit)
Avatar

I'm trying to dynamically add a date property to a WPF property grid at run-time, since it is retrieved from a database. I can get the date property to properly appear via XAML code:

<propgrid:PropertyGrid Name="propertyGrid1"
    Height="217"
    HorizontalAlignment="Left"
    Margin="47,36,0,0"
    VerticalAlignment="Top"
    Width="508" IsSummaryVisible="False">
  <propgrid:PropertyGrid.Items>
    <propgrid:PropertyGridCategoryItem DisplayName="DateTime">
      <propgrid:PropertyGridPropertyItem
          DisplayName="DateTimeEditBox (date only)"
          Description="A DateTimeEditBox used to modify the date of a DateTime.">
        <propgrid:PropertyGridPropertyItem.Value>
          <system:DateTime>10/31/2008 12:00:00</system:DateTime>
        </propgrid:PropertyGridPropertyItem.Value>
        <propgrid:PropertyGridPropertyItem.DefaultValue>
          <system:DateTime>1/1/2008 12:00:00</system:DateTime>
        </propgrid:PropertyGridPropertyItem.DefaultValue>
        <propgrid:PropertyGridPropertyItem.ValueTemplate>
          <DataTemplate>
            <editors:DateTimeEditBox
                Margin="0" BorderThickness="0"
                Value="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type propgrid:IPropertyDataAccessor}}, Mode=TwoWay}"
                Format="d" />
          </DataTemplate>
        </propgrid:PropertyGridPropertyItem.ValueTemplate>
      </propgrid:PropertyGridPropertyItem>
    </propgrid:PropertyGridCategoryItem>
  </propgrid:PropertyGrid.Items>
</propgrid:PropertyGrid>

However, I have a hard time converting this into equivalent C# code. The following C# code does not work. If I comment out the Value property assignment for the DateTimeEditBox object, only a blank value cell is displayed.

propertyGrid1.IsSummaryVisible = false;
propertyGrid1.Items.Clear();

DateTimeEditBox dateTimeEditor = new DateTimeEditBox();
dateTimeEditor.Margin = new Thickness(0);
dateTimeEditor.BorderThickness = new Thickness(0);
dateTimeEditor.Format = "d";

// This line emits a compile error
dateTimeEditor.Value =
    "{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type propgrid:IPropertyDataAccessor}}, Mode=TwoWay}";   

PropertyGridPropertyItem item = new PropertyGridPropertyItem();
item.DisplayName = "DateTimeEditBox (date only)";
item.Description = "A DateTimeEditBox used to modify the date of a DateTime.";
item.ValueTemplate = new DataTemplate(dateTimeEditor);
item.ValueType = typeof(DateTime);
item.DefaultValue = DateTime.Now;
item.Value = DateTime.Now;
propertyGrid1.Items.Add(item);
 

Any help would be greatly appreciated.

Bruce Lum
Developer
Contact Innovations Inc.

Comments (3)

Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Bruce,

It's difficult to create a DataTemplate properly in code.  I'd recommend that you make your DateTimeEditBox-based DataTemplate in your app's Resouces and then use a FindResource() call to get it and assign it to item.ValueTemplate.  That way, you can skip the whole DateTimeEditBox configuration part in C#.

On a side note, the Value line you have there is invalid as VS reports.  You'd need to create a Binding programmatically and then call SetBinding to apply it on the target control.


Actipro Software Support

Posted 3 years ago by Bruce Lum
Avatar

Thanks for your reply.

I wouldn't know how to make a DataTemplate in my application's Resources, let alone make any Resources, because of my lack of knowledge to do so.

However, I found that the following code is working so far, but haven't fully tested it. The code is derived from that of another post.

FrameworkElementFactory factory = new FrameworkElementFactory(typeof(DateTimeEditBox));
factory.SetValue(DateTimeEditBox.MarginProperty, new Thickness(0));
factory.SetValue(DateTimeEditBox.IsReadOnlyProperty, false);
factory.SetValue(DateTimeEditBox.BorderThicknessProperty, new Thickness(0));
factory.SetValue(DateTimeEditBox.FormatProperty, "MMM dd yyyy");

RelativeSource relativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(IPropertyDataAccessor), 1);
factory.SetBinding(DateTimeEditBox.ValueProperty, new Binding("Value") { RelativeSource = relativeSource, Mode = BindingMode.TwoWay });   

PropertyEditor propertyEditor = new PropertyEditor() { PropertyType = typeof(DateTime), ValueTemplate = new DataTemplate() { VisualTree = factory } };
propertyGrid1.PropertyEditors.Add(propertyEditor);

PropertyGridPropertyItem item = new PropertyGridPropertyItem();
item.Tag = 3;
item.DisplayName = "DateTime";
item.Description = "DateTime object";
item.ValueType = typeof(DateTime);
item.DefaultValue = DateTime.Now;
item.Value = DateTime.Now;
propertyGrid1.Items.Add(item);
 

I don't quite fully understand the code that creates the property editor. It does display a Date/Time editor for just the date (in the month day, year format).

Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Bruce,

For a DataTemplate, you just copy the DataTemplate you posted in XAML, add an x:Key="SomeKeyValue" attribute to it and put it your Application.Resources.  Then doing a 'this.FindResource("SomeKeyValue") as DataTemplate' call should be able to locate and return it and prevent the whole element factory section of logic you are doing.  There should be a lot of help on the web for putting DataTemplates in Application.Resources and how all that works.

[Modified 3 years ago]


Actipro Software Support

The latest build of this product (v2019.1 build 0682) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.