Search code examples
c#wpfpropertygrid

WPF Extended Toolkit PropertyGrid: Select property


I want to set the focus on the first item of the property grid. So after adding an object and bind it to the PropertyGrid, you can change the first property.

I tried this, but dont work:

propertyGrid.Focus();
propertyGrid.SelectedProperty = propertyGrid.Properties[0];

Solution

  • Unfortunately there seems to be no built-in solution to this.

    My suggested solution is more like a Workaround, but it should properly Visual-Select the SelectedProperty if it's been set on codebehind.

    First of all, we need some Extensions:

     public static class Extensions {
        public static T GetDescendantByType<T>(this Visual element) where T : class {
          if (element == null) {
            return default(T);
          }
          if (element.GetType() == typeof(T)) {
            return element as T;
          }
          T foundElement = null;
          if (element is FrameworkElement) {
            (element as FrameworkElement).ApplyTemplate();
          }
          for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++) {
            var visual = VisualTreeHelper.GetChild(element, i) as Visual;
            foundElement = visual.GetDescendantByType<T>();
            if (foundElement != null) {
              break;
            }
          }
          return foundElement;
        }
    
        public static void BringItemIntoView(this ItemsControl itemsControl, object item) {
          var generator = itemsControl.ItemContainerGenerator;
    
          if (!TryBringContainerIntoView(generator, item)) {
            EventHandler handler = null;
            handler = (sender, e) =>
            {
              switch (generator.Status) {
                case GeneratorStatus.ContainersGenerated:
                  TryBringContainerIntoView(generator, item);
                  break;
                case GeneratorStatus.Error:
                  generator.StatusChanged -= handler;
                  break;
                case GeneratorStatus.GeneratingContainers:
                  return;
                case GeneratorStatus.NotStarted:
                  return;
                default:
                  break;
              }
            };
    
            generator.StatusChanged += handler;
          }
        }
    
        private static bool TryBringContainerIntoView(ItemContainerGenerator generator, object item) {
          var container = generator.ContainerFromItem(item) as FrameworkElement;
          if (container != null) {
            container.BringIntoView();
            return true;
          }
          return false;
        }
    
      }
    

    After this, you can easily do the following:

    //Register to the SelectedPropertyItemChanged-Event
    this._propertyGrid.SelectedPropertyItemChanged += this.PropertyGridSelectedPropertyItemChanged;
    //Set any Property by index
    this._propertyGrid.SelectedProperty = this._propertyGrid.Properties[3];
    

    Finally do the magically Highlighting

    private void PropertyGridSelectedPropertyItemChanged(object sender, RoutedPropertyChangedEventArgs<PropertyItemBase> e) {
          var pic = this._propertyGrid.GetDescendantByType<PropertyItemsControl>();
          pic.BringItemIntoView(e.NewValue);
          // UPDATE -> Move Focus to ValueBox
          FocusManager.SetFocusedElement(pic,e.NewValue);
          var xx = Keyboard.FocusedElement as UIElement;
          xx?.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
        }
    

    Closure

    The key to everything here is, knowing about the PropertyItemsControl which is an ItemsControl holding all the Properties.

    Hope this helps!

    Credits

    Bring ItemsControl into view
    Get Nested element from a Control