要传递给命令 WPF 的多个参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5105233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiple Parameter to pass to Command WPF
提问by cjroebuck
Possible Duplicate:
Passing two command parameters using a WPF binding
可能的重复:
使用 WPF 绑定传递两个命令参数
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 previousvalues of a certain property, e.g.:
在我的 VM 中,我有一个List<TicketBase> Tickets
. 当用户单击我的应用程序上的按钮时,他们希望查看某个属性的先前值列表,例如:
<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:
如您所见,我将我的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
is another collection that I set as ItemsSource
on my grid)
(ValueHistory
是我ItemsSource
在网格上设置的另一个集合)
However I need to also pass in the propertyname 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?
所以问题基本上是将属性名称作为另一个参数传入我的命令的最干净的方法是什么?
回答by Fredrik Hedblad
See this question
Passing two command parameters using a WPF binding
请参阅此问题
使用 WPF 绑定传递两个命令参数
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
必须像您说的那样使用附加属性。要将两个参数传递给命令,这样的事情应该可以工作
<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();
}
}
回答by cjroebuck
I got this working without resorting to Attached Properties by using the x:Name
property in the Xaml and then passing this on to my CommandParameter as a MultiBinding along with the Tag. From Front to Back:
通过使用x:Name
Xaml 中的属性,然后将其作为 MultiBinding 与标签一起传递给我的 CommandParameter,我无需求助于附加属性即可完成此工作。从前到后:
In my View:
在我看来:
<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}"/>
In the style for each button:
在每个按钮的样式中:
<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>
In my Converter:
在我的转换器中:
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);
}
}
In my View Model:
在我的视图模型中:
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)
}
I am now receiving the Type and PropertyName in my Command. Now, I just need to compile a lambda expression at runtime to dynamically Select the PropertyName from the Type.
我现在在我的命令中收到 Type 和 PropertyName。现在,我只需要在运行时编译一个 lambda 表达式来动态地从 Type 中选择 PropertyName。