首页 > 解决方案 > 如何编写可以承载可变数量的子属性/元素/xaml-tags 的行为

问题描述

我创建了一个Interaction.Behavior需要接收可变数量输入的行为。

为此,该行为具有一个List<>Dependency 属性来接收内容:

private static readonly DependencyPropertyKey FocusTargetsPropertyKey = DependencyProperty.RegisterReadOnly("Targets", typeof(List<FocusTarget>), typeof(StatefulFocusManagerBehavior), new PropertyMetadata(new List<FocusTarget>()));

public static readonly DependencyProperty FocusTargetsProperty = FocusTargetsPropertyKey.DependencyProperty;

public List<FocusTarget> Targets
{
    get => (List<FocusTarget>)this.GetValue(FocusTargetsProperty);
    set => this.SetValue(FocusTargetsProperty, value);
}

并且内容被实现为一个FocusTarget派生自的类FrameworkElement

public class FocusTarget : FrameworkElement
{
    
    #region DepProp: FocusTarget

    public static readonly DependencyProperty FocusTargetProperty = DependencyProperty.Register("Target", typeof(FrameworkElement), typeof(FocusTarget), new PropertyMetadata(null));

    public FrameworkElement Target
    {
        get => (FrameworkElement)this.GetValue(FocusTargetProperty);
        set => this.SetValue(FocusTargetProperty, value);
    }

    #endregion

    #region DepProp: StateName

    public static readonly DependencyProperty StateNameProperty = DependencyProperty.Register("StateName", typeof(string), typeof(FocusTarget), new PropertyMetadata(null));

    public string StateName
    {
        get => (string)this.GetValue(StateNameProperty);
        set => this.SetValue(StateNameProperty, value);
    }

    #endregion
}

行为声明如下:

<b:Interaction.Behaviors>
    <behav:StatefulFocusManagerBehavior FocusTarget="{Binding ElementName=txtResponse}">
        <behav:StatefulFocusManagerBehavior.Targets>
            <behav:FocusTarget Target="{Binding ElementName=txtResponse}"  StateName="Text"  />
            <behav:FocusTarget Target="{Binding ElementName=QnAToggle}"    StateName="Toggle"/>
        </behav:StatefulFocusManagerBehavior.Targets>
    </behav:StatefulFocusManagerBehavior>
</b:Interaction.Behaviors>

现在有什么有效的:

我确实怀疑这可能是一个 DataContext 问题,但无法验证也无法消除它,这让我对可能的问题和解决方案感到困惑。

我试图设置 DataContext 但这个绑定不起作用并给我 null:

<behav:FocusTarget Target="{Binding ElementName=txtResponse}"   
                   StateName="Text"
                   DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}"  />

标签: c#wpfxamlbindingbehavior

解决方案


继承数据上下文和访问行为集合中的元素不能以这种方式工作,因为该集合不在可视树中,也不是启用绑定的FrameworkElement或。Freezable

将 更改FocusTargetsProperty为 aFreezableCollection<FocusTarget>而不是 a List<FocusTarget>。此外,请确保您在构造函数中分配了集合的新实例。

public class StatefulFocusManagerBehavior : Behavior<FrameworkElement>
{
   private static readonly DependencyPropertyKey FocusTargetsPropertyKey = DependencyProperty.RegisterReadOnly("Targets", typeof(FreezableCollection<FocusTarget>), typeof(StatefulFocusManagerBehavior), new PropertyMetadata(null));

   public static readonly DependencyProperty FocusTargetsProperty = FocusTargetsPropertyKey.DependencyProperty;

   public FreezableCollection<FocusTarget> Targets
   {
      get => (FreezableCollection<FocusTarget>)this.GetValue(FocusTargetsProperty);
      set => this.SetValue(FocusTargetsProperty, value);
   }

   public StatefulFocusManagerBehavior()
   {
      SetValue(FocusTargetsPropertyKey, new FreezableCollection<FocusTarget>());
   }
}

然后,不是继承自FrameworkElementin ,而是FocusTarget派生自Freezable

public class FocusTarget : Freezable
{
   protected override Freezable CreateInstanceCore()
   {
      return new FocusTarget();
   }

   // ...your other code.
}

推荐阅读