问题描述
我想设计一个 DataTemplateSelector 将给定的值与传入的参数进行比较,并在值优劣时选择正确的模板
I want to design a DataTemplateSelector who compare the given value with a one passed in parameter and choose the right template if the value is superior or inferior
我带来了以下内容:
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;
}
}
和 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>
如果手动设置 valueToCompare 参数(此处为 12),则此方法非常有效.当我尝试使这个动态化时,通过应用绑定,我收到以下错误:
This works pretty fine if valueToCompare parameter is set manually (here with 12).When I try to make this one dynamic, by applying a binding I got the following error :
不能在类型的ValueToCompare"属性上设置绑定"'InferiorSuperiorTemplateSelector'.绑定"只能设置在DependencyObject 的 DependencyProperty.
问题来了:我们如何在 DataTemplateSelector 中声明一个 DependencyProperty 或者是否有其他选择来实现这个目标?我尝试使用通常的方式定义依赖项属性,但我无法重新定义 SetValue 和 GetValue 方法.
And here comes the problem : how can we declare a DependencyProperty in a DataTemplateSelector or is there any other option to acheve this goal ?I tried to define a dependencyproperty using the usual way but I can't resole the SetValue and GetValue methods.
提前致谢.
作为上述解决方案的附录,这里是我的示例的固定 XAML 代码.
EDIT : As an appendix of the solution mentionned above, 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>
代码的其他部分类似.
推荐答案
从错误中可以明显看出您只能绑定依赖属性.但是因为它已经从 DataTemplateSelector
继承,所以你不能从 DependencyObject 类继承.
As evident from the error you can only bind with dependency property. But since it's already inheriting from DataTemplateSelector
, you cannot inherit from DependencyObject class.
所以,我建议创建一个 附加属性 用于绑定目的.但是 catch 附加属性只能应用于从 DependencyObject 派生的类.
So, I would suggest to create an Attached property for binding purpose. But catch is attached property can only be applied on class deriving from DependencyObject.
因此,您需要稍作调整才能使其适合您.让我一步一步解释.
So, you need to tweak a bit to get it working for you. Let me explain step by step.
首先 - 按照上面的建议创建附加属性:
First - Create 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));
}
第二 - 就像我说的只能在派生自 DependencyObject 的对象上设置,所以在 ContentControl 上设置:
Second - Like I said it can be set only on object deriving from DependencyObject, so set it on 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>
第三.- 现在您可以从作为参数传递的容器对象中获取模板内的值.使用 VisualTreeHelper 获取 Parent (ContentControl) 并从中获取附加属性的值.
Third. - Now you can get the value inside template from container object passed as parameter. Get Parent (ContentControl) using VisualTreeHelper and get value of 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;
}
你也可以像这样获得 ContentControl (container as FrameworkElement).TemplatedParent
.
Also you can get ContentControl like this (container as FrameworkElement).TemplatedParent
.
这篇关于将属性绑定到 DataTemplateSelector的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!