【问题标题】:Possible to use constant/static value inside a binding in XAML?可以在 XAML 的绑定中使用常量/静态值吗?
【发布时间】:2018-06-11 10:51:18
【问题描述】:

我们使用以下机制/语法在 XAML 中绑定命令:

Command="{Binding CommandAggregator[FooCmd], Mode=OneTime}"

这里,CommandAggregator 是一个对象,您可以使用索引器(带有string 参数)来获取实际命令。

向聚合器注册的命令让我有些烦恼,因为我们仍在使用魔术字符串作为命令名称,如下所示:

this.CommandAggregator.SetCommand("FooCmd", new RelayCommand(execute, canExecute));

虽然我不一定喜欢这整个过程,但我无法改变太多。我现在想做的一件事是通过将魔术字符串设为常量或静态CommandName 类中的static readonly string 对象来退出使用魔术字符串。

但是是否可以在 XAML 中定义绑定并引用常量(比如CommandName.Foo)?想过用{x:Static ...},但是不知道怎么把返回值放到索引器中。

【问题讨论】:

  • 可以绑定静态属性:stackoverflow.com/a/31611110/1136211
  • @Clemens 这看起来很有希望,但我无法让Binding CommandAggregator[(common:CommandName.Foo)] 工作;输出中也没有绑定错误。我现在将尝试提供整个路径。代码完成确实为我提供了 common:CommandName 部分,但没有提供任何属性或常量。
  • 您不能在绑定属性路径中使用除文字(字符串或整数)键之外的任何其他内容。在您的 CommandAggregator 类中声明静态属性并绑定 Binding (local:CommandAggregator.FooCmd)
  • @Clemens 啊,这就是原因!我将不得不检查我是否可以这样做(因为它是一个外部组件)。也许我在这里不走运。非常感谢您的建议,我确实学到了一些新东西!

标签: wpf xaml data-binding constants


【解决方案1】:

你可以实现一个IValueConverter,它将根据转换器参数从CommandAggregator返回一个命令:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    var aggregator = value as CommandAggregator;
    var cmd = parameter as string;
    if (aggregator != null && cmd != null)
       return aggregator[cmd];
    return null;
}

并从 xaml 传递参数:

Command="{Binding Path=CommandAggregator,
                  Converter={StaticResource MyConverter}, 
                  ConverterParameter={x:Static Constants.FooCmd},
                  Mode=OneTime}"

【讨论】:

  • 谢谢,我刚试过,效果很好。它有点冗长,但我认为仍然有益。该代码也不太可能更改,但可能会被复制/粘贴以进行新的命令注册。顺便说一句,您忘记将 Converter={StaticResource MyConverter} 部分添加到命令绑定中。
【解决方案2】:

不确定这是否是最好的,但它对我有用。我不喜欢我的调试器中出现这么多 CmdWhatEvers 的 Relay 命令,所以将它们移到字典中,这看起来类似于您的 CommandAggregator,然后用静态字符串对它们进行索引(魔术字符串对我造成了如此多的绑定失败。 ) 无论如何,我的字符串常量存在于一个静态类中

internal static class Str
{
    public static readonly string CmdReset = "CmdReset";
}

在视图模型中

internal class CtrlVm : ViewModelBase
{
    public Dictionary<string, IRelayCommand> Commands { get; }

    public CtrlVm()
    {
        Commands = new Dictionary<string, IRelayCommand>()
        {
            // My relay command class takes, Execute, CanExecute
            //  and a Header parameter, that I use in binding
            Str.CmdReset, new RelayCommand(Reset, CanReset, "Reset");
        },
    }
    private bool CanReset(object parameter)
    {
        return bHasChanges; // or whatever
    }
    private void Reset(object parameter)
    {
        // do the reset work
    }
}

然后在 Xaml <Button Command= "{Binding Commands[CmdReset]}" Content= "{Binding Commands[CmdReset].Header}"/>

【讨论】:

    猜你喜欢
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 2017-09-01
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    相关资源
    最近更新 更多