Hi,
I added custom editor template for some property type. I.e. we have object of type
class
Foo
{
public
Bar Bar1 {
get
;
set
; }
public
Bar Bar2 {
get
;
set
; }
// properties of other type here
}
class
Bar
{
public
string
Name {
get
;
set
; }
public
int
Value {
get
;
set
; }
}
Object of type Foo bound to property grid. In AutoGeneratingPropertyDefinition event handler, I select my custom template for all properties of type Bar:
if
(e.PropertyDefinition.SourceProperty.PropertyType ==
typeof
(Bar))
e.PropertyDefinition.EditorTemplate = Resources[
"barTemplate"
]
as
DataTemplate;
And here goes the problem. Inside my template I can't bind to the properties of Bar1 and Bar2. E.g.
<
DataTemplate
x:Key
=
"barTemplate"
>
<
TextBlock
Text={Binding Name}/>
</
DataTemplate
>
Data template bound to the whole Foo object, not to Bar1 or Bar2 objects. If I change binding to {Binding Bar1.Name}, then template will display data. But I want to create custom editor for all properties of some type (Bar, Datetime, etc) and avoid property name in template binding path (Bar1.Name, Bar2.Name, etc). How can I achieve that?
Btw I use Silverlight 5 and implicit data templates available.
Thanks!
11 Answers, 1 is accepted
I would advise you to use our AutoBind attached behavior alongside with a DataTemplateSelector. Please, refer to this demo that seems to be very similar to you scenario.
Regards,
Ivan Ivanov
the Telerik team
Hi Ivan,
Thanks, but I have same problem with TemplateSelector. Here is implementation:
public
class
PropertyGridDataTemplateSelector : DataTemplateSelector
{
public
override
DataTemplate SelectTemplate(
object
item, DependencyObject container)
{
if
(item
is
PropertyDefinition)
{
var propertyDefinition = (PropertyDefinition)item;
if
(propertyDefinition.SourceProperty.PropertyType ==
typeof
(Bar))
return
BarDataTemplate;
}
return
base
.SelectTemplate(item, container);
}
public
DataTemplate BarDataTemplate {
get
;
set
; }
}
Here is how I apply it:
<
navigation:Page.Resources
>
<
local:PropertyGridDataTemplateSelector
x:Key
=
"templateSelector"
>
<
local:PropertyGridDataTemplateSelector.BarDataTemplate
>
<
DataTemplate
>
<
TextBlock
Text
=
"{Binding Name}"
/>
</
DataTemplate
>
</
local:PropertyGridDataTemplateSelector.BarDataTemplate
>
</
local:PropertyGridDataTemplateSelector
>
</
navigation:Page.Resources
>
<
Grid
x:Name
=
"LayoutRoot"
>
<
telerik:RadPropertyGrid
EditorTemplateSelector
=
"{StaticResource templateSelector}"
/>
</
Grid
>
And I get same error as with selecting datatemplate in AutoGeneratingPropertyDefinition event handler:
System.Windows.Data Error: BindingExpression path error: 'Name' property not found on 'SilverlightApplication1.Foo' 'SilverlightApplication1.Foo' (HashCode=15472207). BindingExpression: Path='Name' DataItem='SilverlightApplication1.Foo' (HashCode=15472207); target element is 'System.Windows.Controls.TextBlock' (Name=''); target property is 'Text' (type 'System.String')..
Any suggestions how to use binding in editor template?
Their Default DataContext of PropertyGridField is RadPropertyGrid's Item, which is an instance of Foo in your scenario. Trying to set such DataTemplate, will result in BindingExpressionPath error as there is no Name property of type Foo. The correct way to define a binding path to a nested property would be to list all the property level names, separate by dorts(i.e. Bar2.Name) Moreover, reading your previous post left me with the impression that you want to use one DataTemplate for multiple PropertyDefinition instances. In order to achieve this, you can use the AutoBind attached behavior. Please, refer to the demo example that I have proposed (especially the way in which the DataTemplates are defined).
Regards,
Ivan Ivanov
the Telerik team
Hi,
"Trying to set such DataTemplate, will result in BindingExpressionPath error as there is no Name property of type Foo."
That's what I'm talking about. I provided whole error message for you to see the problem.
"The correct way to define a binding path to a nested property would be to list all the property level names, separate by dorts(i.e. Bar2.Name)"
That's what all my question is about. I want to avoid property name in template binding path. Because I have many properties of type Bar, which have different names (Bar1.Name, Bar2.Name, etc) .
"In order to achieve this, you can use the AutoBind attached behavior. Please, refer to the demo example that I have proposed (especially the way in which the DataTemplates are defined)."
I did all exactly like in demo (see the code I provided in previous message). It's not working.
Regards,
Andreas
Obviously there was some misunderstanding. In order to shed some more light on this approach, I have prepared an example project for you, testing it with our latest binaries. Please, refer to the attachment. Do not hesitate to contact us if you have any further inquiries.
All the best,
Ivan Ivanov
the Telerik team
Hi,
Thanks for sample project. I'll try to explain what we need to implement.
We want to use NestedPropertiesVisibility = Collapsed. And instead of collapsed/expanded rows we want to display custom editor for objects of type Bar..
As editor template we want to use RadDropDownButton. This button will show only Bar.Name. In the dropdowncontent of button custom control will be displayed for setting other Bar's properties. That's an idea. But we faced Binding problem..
Is it possible to create template for Bar and bind its properties?
Thanks,
Andreas
Please, excuse me for the delayed answer and thanks for the clarifications. I believe that I have understood your requirements properly now. I have modified my initial projecet in order to meet them. I am attaching it for your reference.
Greetings,
Ivan Ivanov
the Telerik team
Thanks for response, but thats again the same. You are providing full path for each property. But I don't have that path. I cannot attach project for you (telerik forum has awful restriction for file types).
In my application different objects could be assigned to property grid. So, I don't know which name will have property of type Bar - it could be Bar1, Bar2, Property3, MyProperty, etc. So, I cannot write full path. But I want to display editor for any property of type Bar, regardless which object assigned to property grid.
Thanks,
Andreas
You are right, forums do have some restrictions regarding file attachments. However, you can open a support ticket which will enable you to send us attachments up to 20 mb and will guarantee you high priority support (24 h). On the problem itself, reusing DataTemplates in Silverlight is a very common framework issue, for which there are very few viable solutions. Our AutoBind attached behavior solves it to some extent, but unfortunately it appears not to meet your requirements. On the other hand, each binding requires a properly set Path, in order to work. So that, complete reusing would be a rather difficult task in some occasions (i.e. in the approach that I have illustrated with my previous attached project, a common UserControl definition is kept, but a different DataContext should be specified for each instance). Another option that comes to my mind that would tackle the need of keeping multiple DataContext instances as resources is to load them from xaml strings, with positional parameters, at runtime. Have you considered this as an option? Meanwhile, feel free to open a support ticket and send us the project which you have mentioned so that we could comment on it in our further communication.
All the best,
Ivan Ivanov
the Telerik team
using
System.Windows;
using
System.Windows.Markup;
using
System.Windows.Media;
using
Telerik.Windows.Controls;
using
Telerik.Windows.Controls.Data.PropertyGrid;
namespace
Accellos.Platform.Silverlight.Themes
{
public
class
ThemePropertyGridDataTemplateSelector : DataTemplateSelector
{
public
override
DataTemplate SelectTemplate(
object
item, DependencyObject container)
{
PropertyDefinition pd = item
as
PropertyDefinition;
if
(pd ==
null
)
return
null
;
if
(pd.SourceProperty.PropertyType !=
typeof
(Brush))
return
null
;
return
(DataTemplate)
XamlReader.Load(@"
<DataTemplate
xmlns=
""
http:
//schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=
""
http:
//schemas.microsoft.com/winfx/2006/xaml""
xmlns:telerik=
""
clr-
namespace
:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Input
""
xmlns:AccellosConverters=
""
clr-
namespace
:Accellos.Platform.Silverlight.Converters;assembly=Accellos.Platform.Silverlight
""
>
<Grid>
<Grid.Resources>
<AccellosConverters:ColorToSolidColorBrushConverter x:Key=
""
ColorToSolidColorBrushConverter
""
/>
</Grid.Resources>
<telerik:RadColorPicker SelectedColor=
""
{Binding Path=" + pd.SourceProperty.Name +
@
", Converter={StaticResource ColorToSolidColorBrushConverter}, Mode=TwoWay}"
" HorizontalAlignment="
"Left"
" />
</Grid>
</DataTemplate>");
}
}
}