【问题标题】:Multiple Parameter to pass to Command WPF [duplicate]传递给命令 WPF 的多个参数 [重复]
【发布时间】:2011-07-03 13:51:36
【问题描述】:

我有以下层次结构:

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

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

class TicketTypeB:TicketBase
{
     public string PropertyB { get; set; }
}

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

<Button Tag="{x:Type Types:TicketTypeA}" 
        Command="{Binding ListHistoryCommand}"
        CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" />

如您所见,我将 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);
}

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

但是我还需要传入 property 名称,这样我就可以像这样在网格中显示该属性:

Published Time     |  PropertyA
===================================================
09:00              | <value of PropertyA at 09:00>
08:55              | <value of PropertyA at 08:55>

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

【问题讨论】:

    标签: wpf parameters command


    【解决方案1】:

    看到这个问题
    Passing two command parameters using a WPF binding

    更新
    如果您需要在Button 上同时存储类型和属性名称,则必须使用您所说的附加属性。要将这两个参数传递给命令,这样的事情应该可以工作

    <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>
    

    参数名称行为

    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);
        }
    }
    

    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();
        }
    }
    

    【讨论】:

    • 但它并没有真正解释我可以在哪里存储我的属性名称。因为我已经使用标签来存储类型,我需要另一个地方来存储属性名称。我将考虑向按钮添加附加属性。
    • @cjroebuck:好的。所以你们都想存储它并将它作为命令参数发送?在那种情况下,我认为您将不得不像您说的那样使用附加属性
    • @cjroebuck:查看我的更新答案。您是否有特殊原因将属性存储在Button 本身上,或者您认为这样的想法会起作用吗?也许我在这里遗漏了部分问题:)
    • 我有一组按钮,一个用于各种票类型的每个不同属性。每个按钮的内容都绑定到属性的最新值。当用户单击这些按钮之一时,该属性的历史值会列在网格中。所以是的,我认为按钮是存储属性的明显位置。你有更好的主意吗?
    • @cjroebuck:不,没有更好的主意 :) 只是没有了解您问题的完整背景。现在我明白你为什么需要它了
    【解决方案2】:

    我通过在 Xaml 中使用 x:Name 属性,然后将其作为 MultiBinding 与标记一起传递给我的 CommandParameter,无需借助附加属性即可完成这项工作。从前到后:

    在我看来:

     <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}"/>
    

    在每个按钮的样式中:

     <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>
    

    在我的转换器中:

    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);
            }
    }
    

    在我的视图模型中:

    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)  
    
        }
    

    我现在在我的命令中收到类型和属性名称。现在,我只需要在运行时编译一个 lambda 表达式to dynamically Select the PropertyName from the Type

    【讨论】:

    • 如何创建转换器类的实例以便Converter="{StaticResource propertyConverter}" 可以工作?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 2016-10-25
    • 1970-01-01
    • 2017-01-27
    相关资源
    最近更新 更多