Display of custom controls when user press F2-double clicked

Grids for WPF Forum

Posted 10 years ago by Balaram Barange
Version: 4.5.0487
Avatar
We need to display property control which have custom controls like IP Address, MAC address, etc.

We have populated those controls and other properties using DataTemplate & PropertyGridPropertyItem through Code Behind[this.PropertyControl.Properties.Add(..)). It displays all the controls & works fine.

Now, we dont want to display those control untill user press "F2" or double clicked on that field.

How can I do that, Please suggest using some example?

Comments (4)

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Balaram,

You would probably need to implement that in a control that derives from PropertyGridDataAccessorItem. You would need to:

1. Create a class that derives from PropertyGridDataAccessorItem (e.g. MyPropertyGridDataAccessorItem)
2. Override IsItemItsOwnContainerOverride and GetContainerForItemOverride MyPropertyGridDataAccessorItem, to test for and return a MyPropertyGridDataAccessorItem.
3. Add a dependency property that determines if the controls should be displayed (e.g. IsEditable).
4. Set IsEditable to true when F2 is detected in OnKeyDown, or double clicked.
5. Updated your Value DataTemplates to display the value using a TextBlock unless IsEditable is true on the parent MyPropertyGridDataAccessorItem.

6. Create a class that derives from PropertyGrid (e.g. MyPropertyGrid).
7. Override IsItemItsOwnContainerOverride and GetContainerForItemOverride in MyPropertyGrid, to test for and return a MyPropertyGridDataAccessorItem.

You would probably then want to set IsEditable to false, when the focus is lost or some other event.


Actipro Software Support

Posted 10 years ago by Balaram Barange
Avatar
Thanks for the reply. I have gone through as per steps, but could not implement the desired behaviour. Please look the following sample code.

Can you please update the following example or give ideas about how to achive functionality?

<Window x:Class="EditablePropertyGrid.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:propGrid="clr-namespace:EditablePropertyGrid"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <propGrid:MyPropertyGrid x:Name="propGrid1"  IsCategorized="True" MiscCategoryTitle="General Properties"  >
        </propGrid:MyPropertyGrid>
    </Grid>
</Window>

namespace EditablePropertyGrid
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            Init1();
        }

        class MyEditMode
        {
            public bool IsEditMode { get; set; }
        }

        MyEditMode myEditMode = new MyEditMode();

        private void Init1()
        {
            Binding editModeBinding = new Binding("IsEditMode");
            editModeBinding.Source = myEditMode;

            PropertyGridPropertyItem item = new PropertyGridPropertyItem();
            item.DisplayName = "Combo Property";
            item.Category = "General Properties";
            item.Description = "Description of combobox type";
            item.Category = "General Description";
            item.Value = "1";
            item.SetValue(MyPropertyGridDataAccessorItem.IsEditMode, true);
            this.propGrid1.Properties.Add(item);
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            // Currently it cannot Fire OnEditModePropertyChanged
            myEditMode.IsEditMode = true;
        }
    }

    public class MyPropertyGridDataAccessorItem : PropertyGridDataAccessorItem
    {
        static FrameworkPropertyMetadata propMetaData = new FrameworkPropertyMetadata(false);
        public static readonly DependencyProperty IsEditMode; 

        static MyPropertyGridDataAccessorItem()
        {
            propMetaData.BindsTwoWayByDefault = true;
            propMetaData.PropertyChangedCallback = OnEditModePropertyChanged;

            IsEditMode = DependencyProperty.Register("EditMode", typeof(bool),
                typeof(MyPropertyGridDataAccessorItem), propMetaData);
        }

        public bool EditMode
        {
            get { return (bool)this.GetValue(IsEditMode); }
            set
            {
                this.SetValue(IsEditMode, value);
            }
        }

        private static void OnEditModePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != null)
            {
                (obj as MyPropertyGridDataAccessorItem).ChangeDataTemplate(args);
            }
        }

        private void ChangeDataTemplate(DependencyPropertyChangedEventArgs args)
        {
            // change Value Template
            // ValueTemplate ? Get only
            // How can I change Template to Combobox

            List<string> cb = new List<string>();
            cb.Add("1");
            cb.Add("2");
            cb.Add("3");

            FrameworkElementFactory cmbBox = new FrameworkElementFactory(typeof(ComboBox));
            cmbBox.SetValue(ComboBox.ItemsSourceProperty, cb);
            cmbBox.SetBinding(ComboBox.IsEnabledProperty, new Binding("IsReadOnly") { RelativeSource = new RelativeSource() { AncestorType = typeof(IPropertyDataAccessor) }, Converter = new BooleanNotConverter() });

            this.ValueTemplate.VisualTree = cmbBox;
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is MyPropertyGridDataAccessorItem;
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new MyPropertyGridDataAccessorItem();
        }
    }

    public class MyPropertyGrid : PropertyGrid
    {
        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is MyPropertyGridDataAccessorItem;
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new MyPropertyGridDataAccessorItem();
        }
    }
}
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
You should not change the underlying ValueTemplate like that. Those types of changes will not be picked up dynamically (e.g. you would have to call PropertyGrid.Refresh). Additionally, you should (almost) never set the VisualTree property the way you are. Unless you specifically know that is has not been sealed (which it would be if the DataTemplate was loaded from a XAML resource).

Also, setting the DataTemplate in this manner will override the all the property editor functionality in the PropertyGrid. Really, your MyPropertyGridDataAccessorItem should not be setting the ValueTemplate at all, it just needs to expose a new DependencyProperty (which you have as EditMode). The ValueTemplate should typically be assigned by the PropertyGrid, as defined by you via the PropertyGrid.PropertyEditors or BuiltinEditors.PropertyEditors collections, or by explicitly setting PropertyGridDataAccessorItem.ValueTemplate property (outside of your custom class that is).

What I'm assuming you want to do is have the Value presented by a TextBlock, then when the user presses the F2 key or double clicks, then it would show a ComboBox allow them to modify it. If so, then your DataTemplate should look something like this:
<DataTemplate>
    <Grid>
        <TextBlock x:Name="textBlock" ... />
        <ComboBox x:Name="comboBox" Visibility="Collapsed" ... />
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding EditMode, RelativeSource={RelativeSource AncestorType={x:Type custom:MyPropertyGridDataAccessorItem}}}" Value="true">
            <Setter TargetName="textBlock" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="comboBox" Property="Visibility" Value="Visible" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>
Basically it would show the value using a TextBlock, until EditMode is set to true. At which point, the ComboBox would be shown. Then your MyPropertyGridDataAccessorItem could toggle EditMode when F2 is detected or on a double click.

Note: If you must build the DataTemplate in the code-behind then you would need to translate this obviously.

If you are a customer, then we can provide the DataTemplates for the built-in property editors (just send an email to our support address requesting them). This is helpful because there are several other things that should be hooked up (for example IsLimitedToStandardValues) to keep your DataTemplate generic. Also, this typically helps with building your own DataTemplates.


Actipro Software Support

Posted 10 years ago by Balaram Barange
Avatar
Thanks Team.
The latest build of this product (v2018.1 build 0675) was released 12 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.