我试图创建一个程序,允许我根据不同的要求选择一个程序来启动不同的程序。基本上我有一个JSON文档,指定Name,Path,Icon等,并为每个条目创建一个按钮。
我有一个ButtonDef
类看起来像这样:
public class ButtonDef
{
public int Id { get; set; }
public string Caption { get; set; }
public string Cmd { get; set; }
public string Icon { get; set; }
}
我创建了一个名为ObservableCollection<ButtonDef>
的{{1}},这是我Buttons
中的公共媒体资源,填充的是ViewModel
s。
我有一个ButtonDef
属性和相应的方法来启动程序。
如果我为每个按钮明确创建一个RelayCommand
并在XAML的Command指令中调用它,那么一切都有效,但由于我不知道会有多少个按钮,所以这不是一个好的解决方案。
我的XAML看起来像这样:
RelayCommand
按钮创建正常,标题正确,但命令不会触发。
我怎样才能实现这一目标?
编辑:
<ItemsControl ItemsSource="{Binding Buttons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Caption}" Height="30" Width="50" Margin="10" Command="{Binding DoSomething}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
答案 0 :(得分:1)
虽然@dymanoid提供的链接给了我一些som的见解,但需要做一些调整才能使它有效。
首先在ViewModel
中定义RelayCommand,如下所示:
public RelayCommand<object> DoSomething {get; set;}
初始化RelayCommand属性:
DoSomething = new RelayCommand<object>(parameter => ExecuteSomething(parameter));
void ExecuteSomething(object parameter)
{
// Do your work here
}
<强> XAML 强>
按钮按以下方式声明:
<ItemsControl ItemsSource="{Binding Buttons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Caption}" Height="30" Width="50" Margin="10" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}},Path=DataContext.DoSomething}" CommandParameter="{Binding Cmd}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
其中RelativeSource和&#34; DataContext&#34; Path
的一部分允许访问窗口的DataContext。
导致解决方案的两个链接:
WPF Command Parameter for button inside ItemsControl
和
Pass different commandparameters to same command using RelayCommand WPF
答案 1 :(得分:0)
我不同意这种方法,但我会回答这个问题。
您需要制作一个Binding
对象,然后使用BindingOperations
来应用绑定。我在下面的代码中提供了一个带注释的示例。
通常Commands
CommandParameters
通常不需要通知的约束Command
。因此,我将提供一个快速示例,我希望能够为您提供足够的信息来添加您需要的任何绑定,包括Command
(如果您愿意)。如果Binding
永远不会改变,我强烈建议只设置它;这与使用Mode = OneTime
设置StackPanel
相同。
此示例仅用于说明如何在代码中进行绑定;没有其他的。如果您的MainWindow
名为“root”中有PersonViewModel
(或任何面板),那么您可以复制并粘贴此代码以进行播放。 (也添加必要的using语句)
在这里,我提供了一个简单的CommandParameterBinding
,列出了这些人(人物),然后绑定到列表,仅为此示例添加public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Initialize();
}
public void Initialize()
{
var ids = 0;
var people = new List<PersonViewModel>()
{
new PersonViewModel() { Id = ids++, Name = "Mathew"},
new PersonViewModel() { Id = ids++, Name = "Mark"},
new PersonViewModel() { Id = ids++, Name = "Luke"},
new PersonViewModel() { Id = ids++, Name = "John"}
};
foreach (var person in people)
{
var button = new Button()
{
Content = person.Name,
Command = person.UpdatePersonCommand
};
SetCommandParameterBinding(button, person);
button.Click += (s, e) => MessageBox.Show(button.CommandParameter.ToString());
root.Children.Add(button);
}
}
//This is the method that answers your question
private static BindingExpressionBase SetCommandParameterBinding(ButtonBase button, PersonViewModel person)
{
//This sets a binding that binds the 'Name' property in PersonViewModel
//Leave constructor parameter emtpy to bind to the object itself i.e. new Binding() { Source = Person }; will bind to person
var binding = new Binding(nameof(PersonViewModel.Name)) { Source = person };
//This sets the binding to the button and button CommandParameterProperty
var bindingExpression = BindingOperations.SetBinding(button, ButtonBase.CommandParameterProperty, binding);
return bindingExpression;
}
}
//This isn't a fully written ViewModel obviously. It's just here to make this example work. INotifyPropertyChanged is not completely implemented. It also definitely doesn't belong in this namespace.
public class PersonViewModel : INotifyPropertyChanged
{
public string Name { get; set; }
public int Id { get; set; }
public ICommand UpdatePersonCommand { get; }
public event PropertyChangedEventHandler PropertyChanged;
}
。
Num = Num % 87