2012-04-26 74 views
5

我在至极上自定义的MarkupExtension的工作,我需要从XAML非字符串参数来构建新的对象。是否可以在datacontext范围的字段上使用非字符串参数绑定?用的MarkupExtension绑定参数

换句话说,我怎么能这样做?

<ListBox ItemsSource="{Binding Source={local:MyMarkupExtension {x:Type Button},IncludeMethods={Binding Source=CustomerObject.IsProblematic}}}" /> 

其中IncludeMethods=CustomerObject.IsProblematic给我这个错误:绑定无法在类型“TypeDescriptorExtension”的“IncludeMethods”属性设置。 '绑定'只能在DependencyObject的DependencyProperty上设置。

任何人都可以帮助我吗?

感谢

回答

9

A '绑定' 只能DependencyObject的一个DependencyProperty设置 - 这是真的。问题是MarkupExtension类不是从DependencyObject派生的,这就是为什么无法在其属性上设置绑定的原因。

[编辑]

解决方法是使用ValueConverters。另一个解决方法是更改​​C#语言以允许多重继承。顺便说一句,在Silverlight MarkupExtension实现IMarkupExtension接口,所以我想实现它在我的自定义扩展,并推导出它DependecyObject,加入DependencyProperty那里,集绑定到它。它不会崩溃,但绑定实际上是 ProvideValue()被调用。所以即使在Silverlight中也没有解决方案(或者很难 - 请参阅Klaus78's answer中提供的链接)。在WPF中,MarkupExtension没有实现任何接口,所以你不能绑定到它的属性。

+0

任何人都可以建议我一个解决方法吗? – user1351709 2012-04-26 07:37:07

+0

请看到我的编辑 – EvAlex 2012-04-26 08:02:11

+17

更改C#语言允许多重继承不正是我所说的“解决办法”;) – 2012-04-26 08:11:28

0

此链接信息约

Custom Markup Extension with bindable properties

编辑 有人让我注意,这仅适用于Silverlight的,因为在WPF的MarkupExtension没有实现IMarkupExtension接口。 (谢谢EvAlex)

+0

它仅适用于Silverlight的,因为在WPF的MarkupExtension没有实现IMarkupExtension接口 – EvAlex 2012-04-26 08:02:00

-1

,我发现了这个问题的解决方法。
主要想法是为需要绑定的每个参数定义附加属性。

public class MarkupExtensionWithBindableParam : MarkupExtension 
{ 
    public BindingBase Param1 { get; set; } // its necessary to set parameter type as BindingBase to avoid exception that binding can't be used with non DependencyProperty 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; 
     DependencyObject targetObject; 
     DependencyProperty targetProperty; 

     if (target != null && target.TargetObject is DependencyObject && target.TargetProperty is DependencyProperty) 
     { 
      targetObject = (DependencyObject)target.TargetObject; 
      targetProperty = (DependencyProperty)target.TargetProperty; 
     } 
     else 
     { 
      return this; // magic 
     } 

     // Bind the Param1 to attached property Param1BindingSinkProperty 
     BindingOperations.SetBinding(targetObject, MarkupExtensionWithBindableParam.Param1BindingSinkProperty, Param1); 

     // Now you can use Param1 

     // Param1 direct access example: 
     object param1Value = targetObject.GetValue(Param1BindingSinkProperty); 

     // Param1 use in binding example: 
     var param1InnerBinding = new Binding() { Source = targetObject, Path = new PropertyPath("(0).SomeInnerProperty", Param1BindingSinkProperty) }); // binding to Param1.SomeInnerProperty 
     return param1InnerBinding.ProvideValue(serviceProvider); // return binding to Param1.SomeInnerProperty 
    } 

    private static DependencyProperty Param1BindingSinkProperty = DependencyProperty.RegisterAttached("Param1BindingSink", typeof(object)// set the desired type of Param1 for at least runtime type safety check 
         , typeof(MarkupExtensionWithBindableParam), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); 
} 

用法很简单:

<TextBlock Text={local:MarkupExtensionWithBindableParam Param1={Binding Path="SomePathToParam1"}}/> 
+0

有与*用途*例如一个问题。标记不是必须用引号括起来吗? – OmegaMan 2016-07-22 14:50:15

+1

似乎不起作用; param1Value始终为空 – esskar 2016-09-15 12:48:00