如何编写可以承载可变数量 child properties/elements/xaml-tags 的行为
How to write a behavior that can host a variable number of child properties/elements/xaml-tags
我创建了一个 Interaction.Behavior
行为,需要接收可变数量的输入。
为此,该行为有一个 List<>
依赖关系 属性 来接收内容:
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);
}
并且内容实现为 class 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>
现在有一个有效的方法:
behav:StatefulFocusManagerBehavior
的 FocusTarget
属性 绑定按预期工作
behav:FocusTarget
个实例的 属性 StateName
设置如预期
behav:FocusTarget
个实例的 Target
属性 始终设置为 null
我确实怀疑这可能是 DataContext 问题,但无法验证也无法消除它,让我对可能的问题和解决方案感到困惑。
我尝试设置 DataContext,但此绑定不起作用,并给我 null:
<behav:FocusTarget Target="{Binding ElementName=txtResponse}"
StateName="Text"
DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}" />
继承数据上下文和访问行为集合中的元素不会那样工作,因为集合不在可视化树中,也不是启用绑定的 FrameworkElement
或 Freezable
。
将 FocusTargetsProperty
更改为 FreezableCollection<FocusTarget>
而不是 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>());
}
}
然后,不是从 FocusTarget
中的 FrameworkElement
继承,而是从 Freezable
.
派生
public class FocusTarget : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new FocusTarget();
}
// ...your other code.
}
我创建了一个 Interaction.Behavior
行为,需要接收可变数量的输入。
为此,该行为有一个 List<>
依赖关系 属性 来接收内容:
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);
}
并且内容实现为 class 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>
现在有一个有效的方法:
behav:StatefulFocusManagerBehavior
的FocusTarget
属性 绑定按预期工作behav:FocusTarget
个实例的 属性StateName
设置如预期behav:FocusTarget
个实例的Target
属性 始终设置为 null
我确实怀疑这可能是 DataContext 问题,但无法验证也无法消除它,让我对可能的问题和解决方案感到困惑。
我尝试设置 DataContext,但此绑定不起作用,并给我 null:
<behav:FocusTarget Target="{Binding ElementName=txtResponse}"
StateName="Text"
DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}" />
继承数据上下文和访问行为集合中的元素不会那样工作,因为集合不在可视化树中,也不是启用绑定的 FrameworkElement
或 Freezable
。
将 FocusTargetsProperty
更改为 FreezableCollection<FocusTarget>
而不是 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>());
}
}
然后,不是从 FocusTarget
中的 FrameworkElement
继承,而是从 Freezable
.
public class FocusTarget : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new FocusTarget();
}
// ...your other code.
}