Bind Property to DataTemplateSelector

I want to create a DataTemplateSelector that compares the given value with the one passed in the parameter and selects the correct template if the value is superior or inferior

I came with the following:

class InferiorSuperiorTemplateSelector : DataTemplateSelector { public DataTemplate SuperiorTemplate { get; set; } public DataTemplate InferiorTemplate { get; set; } public double ValueToCompare { get; set; } public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container) { double dpoint = Convert.ToDouble(item); return (dpoint >= ValueToCompare || dpoint == null) ? SuperiorTemplate : InferiorTemplate; } } 

and xaml:

 <Grid> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="30" /> <RowDefinition Height="30" /> </Grid.RowDefinitions> <TextBox Name="theValue" Grid.Row="0">1</TextBox> <ContentControl Grid.Row="2" Content="{Binding ElementName=theValue, Path=Text}" > <ContentControl.ContentTemplateSelector> <sel:InferiorSuperiorTemplateSelector ValueToCompare="12" SuperiorTemplate="{StaticResource posTemplate}" InferiorTemplate="{StaticResource negTemplate}" /> </ContentControl.ContentTemplateSelector> </ContentControl> </Grid> 

This works very well if valueToCompare is set manually (here from 12). When I try to make this one dynamic using binding, I got the following error:

Binding cannot be set in the ValueToCompare property of type 'InferiorSuperiorTemplateSelector. Binding can only be set to the DependencyProperty of a DependencyObject.

And here's the problem: how can we declare DependencyProperty in a DataTemplateSelector or is there another option to achieve this? I tried to define the dependency property using the usual method, but I can not change the SetValue and GetValue methods.

Thanks in advance.

EDIT: as an application of the above solution, here is the fixed XAML code of my sample.

  <TextBox Name="theValue" Grid.Row="0">1</TextBox> <TextBox Name="theValueToCompare" Grid.Row="1">50</TextBox> <ContentControl Grid.Row="2" Content="{Binding ElementName=theValue, Path=Text}" local:DataTemplateParameters.ValueToCompare="{Binding ElementName=theValueToCompare, Path=Text}"> <ContentControl.ContentTemplateSelector> <local:InferiorSuperiorTemplateSelector SuperiorTemplate="{StaticResource posTemplate}" InferiorTemplate="{StaticResource negTemplate}" /> </ContentControl.ContentTemplateSelector> </ContentControl> 

Other parts of the code are similar.

+7
wpf xaml
source share
1 answer

As you can see from the error , you can only bind to the dependency property . But since it already inherits from the DataTemplateSelector , you cannot inherit the DependencyObject class.

So, I would suggest creating an Attached property for the binding purpose. But the catch property is bound only to the class derived from DependencyObject.

So, you need a little tweak to make it work for you. Let me explain step by step.


First one . Create an attached property as suggested above:

 public class DataTemplateParameters : DependencyObject { public static double GetValueToCompare(DependencyObject obj) { return (double)obj.GetValue(ValueToCompareProperty); } public static void SetValueToCompare(DependencyObject obj, double value) { obj.SetValue(ValueToCompareProperty, value); } public static readonly DependencyProperty ValueToCompareProperty = DependencyProperty.RegisterAttached("ValueToCompare", typeof(double), typeof(DataTemplateParameters)); } 

Second one . As I said, it can only be set for an object originating from DependencyObject, so set it to ContentControl:

 <ContentControl Grid.Row="2" Content="{Binding Path=PropertyName}" local:DataTemplateParameters.ValueToCompare="{Binding DecimalValue}"> <ContentControl.ContentTemplateSelector> <local:InferiorSuperiorTemplateSelector SuperiorTemplate="{StaticResource SuperiorTemplate}" InferiorTemplate="{StaticResource InferiorTemplate}" /> </ContentControl.ContentTemplateSelector> </ContentControl> 

Third . - Now you can get the value inside the template from the container object passed as a parameter. Get Parent (ContentControl) using VisualTreeHelper and get the value of the attached property from it.

 public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container) { double dpoint = Convert.ToDouble(item); double valueToCompare = (double)VisualTreeHelper.GetParent(container) .GetValue(DataTemplateParameters.ValueToCompareProperty); // HERE // double valueToCompare = (container as FrameworkElement).TemplatedParent; return (dpoint >= valueToCompare) ? SuperiorTemplate : InferiorTemplate; } 

You can also get a ContentControl as follows (container as FrameworkElement).TemplatedParent .

+11
source share

All Articles