2011-02-24 135 views
4

可能重複:
Passing two command parameters using a WPF binding多參數傳遞給命令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; } 
} 

在我的VM我有一個List<TicketBase> Tickets。當用戶點擊我的應用程序的按鈕,他們希望看到的有一定財產的以前值的列表,如:

<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我網的另一個集合)

不過,我還需要通過在屬性名了,所以我可以在網格像這樣只顯示該屬性:

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

所以,問題基本上是什麼屬性名傳遞另一個參數進我的命令最乾淨的方式是什麼?

回答

11

看到這個問題
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> 

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

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

但它並沒有真正解釋在那裏我可以存儲我的屬性名..作爲即時通訊已經在使用該標籤存儲的類型,我需要換個地方來存儲屬性名稱。我會查看添加附加屬性到按鈕。 – cjroebuck 2011-02-24 14:57:57

+0

@cjroebuck:好的。所以你們都希望把它存儲起來並把它作爲CommandParameter發送出去?在這種情況下,我認爲你必須像你說的那樣使用附加屬性 – 2011-02-24 14:59:19

+0

@cjroebuck:查看我更新的答案。你有沒有特別的理由來將這些屬性存儲在'Button'本身上,或者你認爲這樣的想法會起作用嗎?也許我錯過了這裏的一些問題的部分:) – 2011-02-24 15:21:42

5

我得到了這個工作,而不訴諸附加屬性通過使用Xaml和t中的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) 

    } 

我現在在我的Command中接收Type和PropertyName。現在,我只需要在運行時編譯一個lambda表達式to dynamically Select the PropertyName from the Type