Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Parameter to pass to Command WPF [duplicate]

I have the following hierarchy:

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

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

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

In my VM I have a List<TicketBase> Tickets. When a user clicks a button on my app, they want to see a list of previous values of a certain property, e.g.:

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

as you can see, I set my Tag property to TicketTypeA and pass that as parameter to my command:

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 is another collection that I set as ItemsSource on my grid)

However I need to also pass in the property name too, so that I can display just that property in the grid like so:

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

So the question is basically what is the cleanest way to pass in the property name as another parameter into my command?

like image 809
cjroebuck Avatar asked Feb 24 '11 13:02

cjroebuck


People also ask

How to pass multiple command parameters in WPF?

public event EventHandler CanExecuteChanged; private Action<string,string> _execute; public MyCommand(Action<string,string> execute)

What is 2 way binding in WPF?

Bindings that are TwoWay or OneWayToSource listen for changes in the target property and propagate them back to the source, known as updating the source. For example, you may edit the text of a TextBox to change the underlying source value.

What is command parameter WPF?

CommandParameter - represents a user-defined data value that can be passed to the command when it is executed.

What is WPF MultiBinding?

MultiBinding takes multiple values and combines them into another value. There are two ways to do MultiBinding , either using StringFormat or by a converter. The StringFormat. is simple compared to a converter, so we will start with that first.


1 Answers

See this question
Passing two command parameters using a WPF binding

Update
If you need to store both the Type and the Property Name on the Button you'll have to use an attached property like you said. To pass the two parameters to the Command, something like this should work

<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();
    }
}
like image 100
Fredrik Hedblad Avatar answered Sep 22 '22 15:09

Fredrik Hedblad