Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TextBlockEditor : Use Label instead of TextBlock to allow customizing template #1539

Closed
Nfactor26 opened this issue Oct 23, 2019 · 7 comments

Comments

@Nfactor26
Copy link

Nfactor26 commented Oct 23, 2019

Issue Description

  1. TextBlockEditor : TypeEditor<TextBlock> is used in PropertyGrid for displaying readonly properties.
    However, TextBlock control in WPF doesn't allow to override it's Template using a style.
  2. Margin is set to (5,0,0,0) from inside SetControlProperties() of TextBlockEditor which takes precedence over any margin applied from style.

Suggested Solution
Use a Label control instead of TextBlock control for displaying readonly properties since WPF Label control allows overriding it's control template using a style.

@Nfactor26
Copy link
Author

Created pull request #1540 for this issue.
Using TextBox instead of Label however as Label required a custom converter to work properly.

@XceedBoucherS
Copy link
Collaborator

Hi,
You are right, TextBlockEditor.SetControlProperties() modify the Margin and TextTrimming of the editor so a style can't override those values. But if we remove those 2 properties from TextBlockEditor.SetControlProperties() and set them in the style targeting PropertyGridEditorTextBlock (from Aero2.NormalColor.xaml), it fixes the issue.

A user then simply needs to do this in is xaml in order to modify the style:
<Window.Resources> <Style TargetType="{x:Type xctk:PropertyGridEditorTextBlock}"> <Setter Property="FontSize" Value="25" /> <Setter Property="Margin" Value="30,0,0,0" /> </Style> </Window.Resources>

This will be fixed in v3.9.
Thank you.

@Nfactor26
Copy link
Author

True . However, that only solves a part of problem..I was trying to give property grid a custom look to match my application theme and i wanted to have a border around TextBlock with border thickness : (0,0,0,1) . However, i can't do this if TextBlock is used to display property.

@XceedBoucherS
Copy link
Collaborator

XceedBoucherS commented Oct 24, 2019

Hi,
If you know which properties are readonly, you can always use a custom editor made of a border(with a BorderThickness and a TextBlock) for those :
<xctk:PropertyGrid.EditorDefinitions> <xctk:EditorTemplateDefinition TargetProperties="LastName"> <xctk:EditorTemplateDefinition.EditingTemplate> <DataTemplate> <Border BorderThickness="0,0,0,1" BorderBrush="Red"> <TextBlock Text="{Binding Value}" Foreground="Gray" Margin="5,0,0,0" TextTrimming="CharacterEllipsis"/> </Border> </DataTemplate> </xctk:EditorTemplateDefinition.EditingTemplate> </xctk:EditorTemplateDefinition> </xctk:PropertyGrid.EditorDefinitions>

If you don't know which properties are readonly, you can do the same in code-behind:
` <Window.Resources>
< DataTemplate x:Key="BorderTextBlock">
< Border BorderThickness="0,0,0,1"
BorderBrush="Red">
< TextBlock Text="{Binding Value}"
Foreground="Gray"
Margin="5,0,0,0"
TextTrimming="CharacterEllipsis" />
< /Border>
< /DataTemplate>
</Window.Resources>

<xctk:PropertyGrid SelectedObject="{Binding}"
IsPropertyBrowsable="PropertyGrid_IsPropertyBrowsable" /> `

private void PropertyGrid_IsPropertyBrowsable( object sender, Xceed.Wpf.Toolkit.PropertyGrid.IsPropertyBrowsableArgs e ) { var propertyGrid = sender as PropertyGrid; if( propertyGrid != null ) { if( e.PropertyDescriptor.IsReadOnly ) { var etd = new EditorTemplateDefinition() { TargetProperties = new List<string>() { e.PropertyDescriptor.DisplayName } }; etd.EditingTemplate = this.Resources[ "BorderTextBlock" ] as DataTemplate; propertyGrid.EditorDefinitions.Add( etd ); } } }

@Nfactor26
Copy link
Author

Thanks @XceedBoucherS ....I believe the code behind approach should work fine..Wondering , however, whether propertyGrid.EditorDefintions is cleared every time the selected object changes ? Otherwise, there might be a possibility if there is some property X in type A which is readonly and EditorDefintion is now added to propertyGrid and then we try to set type B having property X as well but not marked as readonly , in this case B.X will also be rendered in a readonly mode.
Assuming , above is the case , another option i can think of is to set the editor directly for the PropertyItem while handling PreparePropertyItem event. However, i am not sure how much of a performance penalty that will be , as it will end up creating lots of TextBlock controls when there are several readonly property on each model and selectedobject is changing very frequently.

@XceedBoucherS
Copy link
Collaborator

Hi,
Modifying the Property.SelectedObject do not clear the EditorDefinitions collection. It might be useful to keep it alive when defined in XAML and the SelectedObject is changed.

What I would suggest, is to register to the PropertyGrid.SelectedObjectChanged event and use the callback to clear the EditorDefinitions collection:
private void PropertyGrid_SelectedObjectChanged( object sender, RoutedPropertyChangedEventArgs<object> e ) { var propertyGrid = sender as PropertyGrid; if( (propertyGrid != null) && (propertyGrid.EditorDefinitions != null) ) { propertyGrid.EditorDefinitions.Clear(); } }

You can also use the PreparePropertyItem callback to set the PropertyItem.Editor. It shouldn't affect the performance since all PropertyItems will end up with an Editor (either set by the user or the Default PropertyGrid editors).

@Nfactor26
Copy link
Author

Thanks for sharing !! Appreciate your time !! I should be able to get my stuff working with this information. I will close the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants