Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Properties Panel similar to Visual Studio's

Tags:

c#

wpf

.net-4.0

Just wondering is their any examples or elements which can look very similar to the Properties panel used in Visual Studio? My guess the one in Visual Studio 2010 is built upon WPF, almost definitely a treeview?

like image 812
wonea Avatar asked May 12 '10 16:05

wonea


2 Answers

  • Mindscape has a free one.
  • There is one on CodeProject.
  • Actipro develops a very nice one.
  • As does ComponentOne.
like image 92
Charlie Avatar answered Sep 28 '22 07:09

Charlie


If you want to use some simple XAML, the following is visually identical to the WinForms PropertyGrid but is much easier to work with:

<Style x:Key="InnerBorder" TargetType="{x:Type Border}">
  <Setter Property="BorderThickness" Value="1" />
  <Setter Property="Margin" Value="4" />
  <Setter Property="BorderBrush" Value="#B4B0A8" />
</Style>

<Grid>

  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

  <!-- Main property grid area -->
  <Border Style="{StaticResource InnerBorder}">
    <ListBox
      ItemsSource="{Binding Parameters}"
      IsSynchronizedWithCurrentItem="True"
      KeyboardNavigation.TabNavigation="Continue"
      HorizontalContentAlignment="Stretch" BorderThickness="0">

      <!-- Category grouping rows -->
      <ListBox.GroupStyle>
        <GroupStyle>
          <GroupStyle.HeaderTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding Name}" Background="#D4D0C8" FontWeight="Bold" Padding="2 2 0 4" Margin="0 0 0 3"/>
            </DataTemplate>
          </GroupStyle.HeaderTemplate>
          <GroupStyle.ContainerStyle>
            <Style>
              <Setter Property="Control.Margin" Value="0 0 0 8" />
            </Style>
          </GroupStyle.ContainerStyle>
        </GroupStyle>
      </ListBox.GroupStyle>

      <!-- Item container style -->
      <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
          <Setter Property="Focusable" Value="False" />
          <Setter Property="TabIndex" Value="0" />
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type ListBoxItem}">

                <DockPanel Margin="4 0 0 0" IsKeyboardFocusWithinChanged="DockPanel_IsKeyboardFocusWithinChanged" MouseDown="DockPanel_MouseDown">
                  <TextBlock Name="TitleBlock" Text="{Binding DisplayName}" Width="135" />
                  <ContentPresenter />
                </DockPanel>

                <ControlTemplate.Triggers>
                  <Trigger Property="IsSelected" Value="true">
                    <Setter TargetName="TitleBlock" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                    <Setter TargetName="TitleBlock" Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
                  </Trigger>
                </ControlTemplate.Triggers>

              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </ListBox.ItemContainerStyle>

    </ListBox>
  </Border>

  <!-- Help area -->
  <Border Style="{StaticResource InnerBorder}" Grid.Row="1" DataContext="{Binding Parameters}">
    <StackPanel HorizontalAlignment="Stretch" Margin="2">
      <TextBlock FontWeight="Bold" Text="{Binding /DisplayName}" />
      <TextBlock Text="{Binding /Description}" TextWrapping="Wrap" />
    </StackPanel>
  </Border>

</Grid>

And here is the code behind

private void DockPanel_IsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
{
  var element = (FrameworkElement)sender;
  if(element.IsKeyboardFocusWithin)
  {
    Visual cur = element;
    while(cur!=null && !(cur is ListBoxItem))
      cur = (Visual)VisualTreeHelper.GetParent(cur);
    ((ListBoxItem)cur).IsSelected = true;
  }
}

private void DockPanel_MouseDown(object sender, MouseEventArgs e)
{
  ((FrameworkElement)sender).MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}

private void InitializeView()
{
  var view = CollectionViewSource.GetDefaultView(Parameters);
  if(view.GroupDescriptions.Count==0)
    view.GroupDescriptions.Add(new PropertyGroupDescription("Category"));

  if(view.SortDescriptions.Count==0)
  {
    view.SortDescriptions.Add(new SortDescription("Category", ListSortDirection.Ascending));
    view.SortDescriptions.Add(new SortDescription("DisplayName", ListSortDirection.Ascending));
  }
}

The reason this property grid is nicer to work with in WPF is that you can add any kind of object to the Parameters collection as long as it has a Category, DisplayName, and Description.

If you want to use it to actually display the properties of a specific object, it only takes a few lines to load up the Parameters collection with the appropriate objects.

like image 37
Ray Burns Avatar answered Sep 28 '22 05:09

Ray Burns