多个参数传递给命令WPF

cjr*_*uck 5 parameters wpf command

可能重复:
使用WPF绑定传递两个命令参数

我有以下层次结构:

abstract class TicketBase
{
    public DateTime PublishedDate { get; set; }
}

class TicketTypeA:TicketBase
{
     public string PropertyA { get; set; }
}   

class TicketTypeB:TicketBase
{
     public string PropertyB { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在我的VM中,我有一个List<TicketBase> Tickets.当用户单击我的应用程序上的按钮时,他们希望查看某个属性的先前值列表,例如:

<Button Tag="{x:Type Types:TicketTypeA}" 
        Command="{Binding ListHistoryCommand}"
        CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" />
Run Code Online (Sandbox Code Playgroud)

如您所见,我将我的Tag属性设置为TicketTypeA并将其作为参数传递给我的命令:

private void ListHistory(object o)
{
   if (Tickets.Count == 0)
       return;
   Type ty = o as Type;
   ValueHistory = new ObservableCollection<TicketBase>(GetTicketsOfType(ty).Select(t => t)); // <- Need to return t.PropertyA here, but dynamically
}

IEnumerable<TicketBase> GetTicketsOfType(Type type)
{
    if (!typeof(TicketBase).IsAssignableFrom(type))
        throw new ArgumentException("Parameter 'type' is not a TicketBase");
    return Tickets.Where(p => p.GetType() == type);
}
Run Code Online (Sandbox Code Playgroud)

(ValueHistory是我ItemsSource在网格上设置的另一个集合)

但是我也需要传入属性名称,以便我可以在网格中显示该属性,如下所示:

Published Time     |  PropertyA
===================================================
09:00              | <value of PropertyA at 09:00>
08:55              | <value of PropertyA at 08:55>
Run Code Online (Sandbox Code Playgroud)

所以问题基本上是什么是将属性名称作为另一个参数传入我的命令的最简洁方法?

Fre*_*lad 12

请参阅此问题
使用WPF绑定传递两个命令参数

更新
如果你需要存储类型和属性名称,Button你必须使用你所说的附加属性.要将这两个参数传递给Command,这样的东西应该可以工作

<Button Tag="{x:Type Types:TicketTypeA}"
        local:ParameterNameBehavior.ParameterName="{Binding Source='Parameter A'}"
        Command="{Binding ListHistoryCommand}">
    <Button.CommandParameter>
        <MultiBinding Converter="{StaticResource PassThroughConverter}">
            <Binding Path="Tag" RelativeSource="{RelativeSource Self}"/>
            <Binding Path="(local:ParameterNameBehavior.ParameterName)"
                     RelativeSource="{RelativeSource Self}"/>
        </MultiBinding>
    </Button.CommandParameter>
</Button>
Run Code Online (Sandbox Code Playgroud)

ParameterNameBehavior

public static class ParameterNameBehavior
{
    private static readonly DependencyProperty ParameterNameProperty = 
        DependencyProperty.RegisterAttached("ParameterName",
                                            typeof(string),
                                            typeof(ParameterNameBehavior));
    public static void SetParameterName(DependencyObject element, string value)
    {
        element.SetValue(ParameterNameProperty, value);
    }
    public static string GetParameterName(DependencyObject element)
    {
        return (string)element.GetValue(ParameterNameProperty);
    }
}
Run Code Online (Sandbox Code Playgroud)

PassThroughConverter

public class PassThroughConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return values.ToList();
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}
Run Code Online (Sandbox Code Playgroud)


cjr*_*uck 5

通过使用x:NameXaml中的属性,然后将其作为MultiBinding传递给我的CommandParameter以及Tag,我得到了这个工作,而没有求助于Attached Properties .从正面到背面:

在我看来:

 <Button Content="{Binding PropertyA}" x:Name="PropertyA" Tag="{x:Type Types:TicketTypeA}" Style="{StaticResource LinkButton}"/>

 <Button Content="{Binding PropertyB}" x:Name="PropertyB" Tag="{x:Type Types:TicketTypeB}" Style="{StaticResource LinkButton}"/>
Run Code Online (Sandbox Code Playgroud)

在每个按钮的样式中:

 <Style x:Key="LinkButton" TargetType="Button">
        <Setter Property="Command" Value="{Binding DataContext.ListHistoryCommand, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />

        <Setter Property="CommandParameter">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource propertyConverter}">
                    <MultiBinding.Bindings>
                        <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}"/>
                        <Binding Path="Name" RelativeSource="{RelativeSource Mode=Self}"/>
                    </MultiBinding.Bindings>
                </MultiBinding>
            </Setter.Value>
        </Setter>
Run Code Online (Sandbox Code Playgroud)

在我的转换器中:

public class PropertyConverter : IMultiValueConverter
{
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            //Type t = values[0] as Type;
            //String propName = values[1] as string;

            Type t = values[0] as Type;
            if (t == null)
                return typeof(TicketBase);
            String s = values[1] as String;

            return new Tuple<Type,String>(t,s);
        }
}
Run Code Online (Sandbox Code Playgroud)

在我的视图模型中:

private void ListHistory(object o)
    {
        if (Tickets.Count == 0)
            return;
        var tuple = o as Tuple<Type,String>;

        // Now write some code to dynamically select the propertyName (tuple.Item2) from the type (tuple.Item1)  

    }
Run Code Online (Sandbox Code Playgroud)

我现在在命令中收到Type和PropertyName.现在,我只需要在运行时编译lambda表达式,从Type中动态选择PropertyName.