gpt4 book ai didi

c# - 将命令绑定(bind)到动态创建的按钮

转载 作者:行者123 更新时间:2023-12-03 10:25:54 30 4
gpt4 key购买 nike

我正在尝试创建一个程序,该程序允许我根据不同的要求选择一个程序来启动不同的程序。基本上我有一个 JSON 文档,指定名称、路径、图标等,并为每个条目创建一个按钮。

我有一个 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>调用 Buttons这是我的 ViewModel 中的公共(public)属性(property)填充是 ButtonDef s。

我有一个 RelayCommand将启动程序的属性和相应的方法。

如果我显式创建 RelayCommand,一切正常对于每个按钮并在 XAML 的 Command 指令中调用它,但由于我不知道会有多少按钮,所以这不是一个好的解决方案。

我的 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 DoSomething}" />
</DataTemplate>
</ItemsControl.ItemTemplate>

</ItemsControl>

按钮创建得很好,标题正确,但命令不会触发。

我怎样才能做到这一点?

编辑:
 public class MainViewModel : ViewModelBase
{

public ObservableCollection<ButtonDef> Buttons { get; set; }

public List<DataItem> Items { get; set; }

public RelayCommand DoSomething { get; set; }






/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel(IDataService dataService)
{


Items = new List<DataItem> { new DataItem("Item 1"), new DataItem("Item 2") };

//Items.Add(new DataItem("Item 1"));

if (Buttons == null) Buttons = new ObservableCollection<ButtonDef>();
foreach (var item in Items)
{
Buttons.Add(new ButtonDef
{
Caption = item.Title,
Cmd = "Path to exe"
});
}


}

最佳答案

我不同意这种方法,但我会回答这个问题。

您需要制作 Binding对象,然后使用 BindingOperations应用绑定(bind)。我在下面的代码中提供了一个带有注释的示例。

通常 Commands还不需要通知绑定(bind)CommandParameters经常做。因此,我将提供一个我整理的快速示例,希望能为您提供足够的信息来添加您需要的任何绑定(bind),包括 Command如果你想。如果 Command永不改变我强烈建议只设置它;这与设置 Binding 相同与 Mode = OneTime .

这个例子只是为了展示如何在代码中进行绑定(bind);没有其他的。如果您有 StackPanel (或任何面板)在您的 MainWindow命名为“root”,然后您可以复制并粘贴此代码以使用它。 (也添加必要的 using 语句)

这里我提供一个简单的PersonViewModel ,列出这些人(人物),然后绑定(bind)到列表中,只添加一个 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;
}

关于c# - 将命令绑定(bind)到动态创建的按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50214103/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com