如何将命令绑定添加到动态按钮?

问题描述 投票:0回答:2

经过广泛的研究,我还没有找到这个问题的答案。我有一个列表框,其ItemsSource是Button对象的集合。当我向集合添加一个按钮时,它会正确显示,但是当单击时,该命令不会被执行。我已经实现了RelayCommand,它在我的代码中使用。

C#MVVM WPF

风景

              <ListBox ItemsSource="{Binding Buttons}"
                            HorizontalAlignment="Stretch"
                            VerticalAlignment="Stretch">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Button Margin="5,5,5,5"
                            Content="{Binding Content}"
                            Command="{Binding ExecuteButtonCommand}"
                            CommandParameter="{Binding CommandParameter}"
                            />
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

ViewModel

    public RelayCommand _executeButtonCommand;

    public ICommand ExecuteButtonCommand
    {
        get
        {
            if (_executeButtonCommand == null)
                _executeButtonCommand = new RelayCommand(exec => this.ButtonCommands(param));
            return _executeButtonCommand;
        }
    }

对于测试我有这个代码。

        public void AddButtons()
    {
        Buttons= new ObservableCollection<Button>();
        Button btn = new Button();
        btn.Content = "Generate Files";
        btn.Command = "{Binding ExecuteButtonCommand}";
        btn.CommandParameter = "Files";
        Buttons.Add(btn);
    }

但我无法以这种方式分配命令。按钮的其余部分正常工作。所以我把Command =放在视图中,如上所示。

如果这已得到回答,那么我找不到它。最近的答案是9岁,不起作用。

谢谢你的期待。

c# button mvvm command
2个回答
1
投票

发生的事情是ListBox的DataTemplate试图绑定到一个名为ExecuteButtonCommand的属性,该属性在Button对象中不存在。然后,要绑定参数,您需要指向视图的DataContext。

将其更改为:

<ListBox.ItemTemplate>
    <DataTemplate>
        <Button Margin="5,5,5,5"
                        Content="{Binding Content}"
                        Command="{Binding Command}"
                        CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.MyParameter}"
                        />
    </DataTemplate>
</ListBox.ItemTemplate>

为了澄清,我在ViewModel中创建了一个名为“MyParameter”的属性。此外,在您的代码隐藏中,将按钮创建代码更改为:

Buttons = new ObservableCollection<Button>();
Button btn = new Button();
btn.Content = "Generate Files";
btn.Command = ExecuteButtonCommand;
Buttons.Add(btn);

而你的ExecuteButtonCommand简单地说:

 public ICommand ExecuteButtonCommand
 {
     get
     {
         if (_executeButtonCommand == null)
             _executeButtonCommand = new RelayCommand(ButtonCommands);
         return _executeButtonCommand;
     }
 }

0
投票

我希望用最终结果将其关闭,以防其他人正在寻找相同的答案。 Mari让我直截了当,导致下面这个例子作为最终结果。没有“背后的代码”。按钮的生成在视图模型中完成。创建按钮后,它将添加到按钮集合中,该集合是ListBox的源。我只包含特定于该问题的代码。

这就是最终结果。

风景

                <ListBox ItemsSource="{Binding Buttons, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
                     HorizontalAlignment="Stretch"
                     VerticalAlignment="Stretch"
                     Background="AliceBlue"
                     BorderBrush="Transparent"
                     ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                     SelectedItem="">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel IsItemsHost="True" />
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>                    
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Button Margin="5,5,5,5"
                            Content="{Binding Content}"
                            Command="{Binding Command}"
                            CommandParameter="{Binding CommandParameter}"
                            />
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

ViewModel - 一个switch语句用于确定需要生成哪个按钮。我给了按钮一个名字,因为我希望能够在集合中找到它并设置Enabled属性。但这没用,我仍然没有找到答案。

        public void AddButton(string param)
    {
        Button btn = new Button();
        switch (param)
        {
            case "Files":
                btn.Content = "Do Files";
                btn.CommandParameter = "Files";
                btn.Name = "Files";
                break;
          //More items here
        }
        btn.Command = ExecuteButtonCommand; //The ICommand name. I made this harder than it needed to be!
        Buttons.Add(btn);
    }

        public RelayCommand _executeButtonCommand;
    public ICommand ExecuteButtonCommand
    {
        get
        {
            if (_executeButtonCommand == null)
                _executeButtonCommand = new RelayCommand(param => this.ButtonCommands(param));
            return _executeButtonCommand;
        }
    }

我希望能帮助别人。

© www.soinside.com 2019 - 2024. All rights reserved.