我有一个为按钮添加行为的类,但我想封装添加的行为,以便我也可以将它添加到ButtonBase的其他衍生物中。该行为管理逻辑树的添加,以便我可以制作xaml可组合的多目标命令。
public class MultiCommandButton : Button
{
#region Command
public Collection<object> _logicalChildren { get; set; }
public override IEnumerator LogicalChildren
{
get
{
if(_logicalChildren == null) return base.LogicalChildren;
return this._logicalChildren.GetEnumerator();
}
}
public static void CommandChangedCallback (DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var multitarget = e.NewValue as MultiTargetCommand;
if (multitarget == null) return;
var b = d as MultiCommandButton;
if (b == null) return;
_changeLogicalMultiTargetCommand(b, e.OldValue, e.NewValue);
if (e.OldValue == null) return;
b.RemoveLogicalChild(e.OldValue);
}
public static void _changeLogicalMultiTargetCommand (MultiCommandButton b,
object oldValue, object newValue)
{
var children = b._logicalChildren;
if (children != null && oldValue is MultiTargetCommand)
{
if (children.Contains(oldValue))
{
children.Remove(oldValue);
b.RemoveLogicalChild(oldValue);
children.Add(newValue);
b.AddLogicalChild(newValue);
return;
}
throw new InvalidOperationException("Only one MultiCommand can be set");
}
var baseChildren = b.LogicalChildren;
object content = null;
if (baseChildren != null && baseChildren.MoveNext())
{
content = baseChildren.Current;
}
b._logicalChildren = new Collection<object>();
if (content != null)
b._logicalChildren.Add(content);
b._logicalChildren.Add(newValue);
b.AddLogicalChild(newValue);
}
#endregion
#region Constructor
static MultiCommandButton()
{
CommandProperty.AddOwner(typeof(MultiCommandButton),
new FrameworkPropertyMetadata(CommandChangedCallback));
}
#endregion
}
<StackPanel x:Name="Targets">
<Button x:Name="Button1">
<Button.CommandBindings>
<ctb:OutputToggleEnabledBind />
</Button.CommandBindings>
</Button>
<Button Name="Button2">
<Button.CommandBindings>
<ctb:OutputToggleEnabledBind />
</Button.CommandBindings>
</Button>
<Button Name="Button3">
<Button.CommandBindings>
<ctb:OutputToggleEnabledBind />
</Button.CommandBindings>
</Button>
</StackPanel>
<ctb:MultiCommandButton x:Name="MultiEnable"
CommandParameter="Multi Target">
^^^Multi Target Toggle Enabled^^^
<ctb:MultiCommandButton.Command>
<ctb:MultiTargetCommand
Command="{x:Static ctb:MultiCommands.OutputToggleEnabled}">
<ctb:CommandTarget Target="{Binding ElementName=Button1}" />
<ctb:CommandTarget Target="{Binding ElementName=Button2}" />
</ctb:MultiTargetCommand>
</ctb:MultiCommandButton.Command>
</ctb:MultiCommandButton>
我试图以三种方式实现这一目标......
我试图避免的另一个选择是将成员简化为派生类。
我将一些方法设为静态,希望我可以将它们移动到静态服务类。我遇到的问题是静态方法引用了基类上的受保护的内部属性(例如RemoveLogicalChild
中的FrameworkElement
),因此静态方法由于它们的访问而在词法上绑定到我的派生类符。因此,我无法在不暴露这些属性的情况下将这些方法移动到服务类,并在派生类上使用中继属性。这看起来像代码味道。
我不知道是否有任何类似于接口的方法可以应用于静态成员,因为我无法将静态成员移动到服务类,我可以&#39 ; t使用接口。我也有一个属性是覆盖,我认为这也是一个问题,但似乎可以使用new
关键字:虽然这感觉像特定应用程序的风险,因为WPF可能访问基本属性并忽略新的(我实际上可以在WPF检查器中看到这种差异)。
这样可行,但是创建了可能是静态的方法的不必要的实例版本,并且我可能会因为必须使用new关键字而破坏我覆盖的虚拟FrameworkElement属性的风险。
最干净,最干燥的方法是什么?