【问题标题】:WPF Give every new button the same click command using C#WPF 使用 C# 为每个新按钮提供相同的单击命令
【发布时间】:2017-01-17 14:51:24
【问题描述】:

标题说明了一切。这是我尝试过的,但是当我单击新按钮时,它们什么也不做。我是 WPF 新手,因此请随时转发您可以看到的任何明显的不良做法。

UserInputPage.xaml

<Grid Name="UserInputGrid">               
    <Button Name="FindAddressButton_1" Grid.Row="0" Grid.Column="1" Margin="5,35,0,0" Width="30" Height="20" VerticalAlignment="Top" HorizontalAlignment="left" Click="ClickFindAddress">...</Button>
    <Button Name="NewFileButton" Grid.Row="1" Margin="10,6,0,0" Width="Auto" Height="18" VerticalAlignment="Top" HorizontalAlignment="Left" Click="ClickNewBar">New Item</Button>        
</Grid>

UserInputPage.xaml.cs

    private void ClickNewBar (object sender, RoutedEventArgs e)
    {
        if (FilesList.Items.Count < MAX_ADDRESS_BARS)
        {                
            CreateNewAddressBar();
            CreateFindButton();
        }

        else
        {
            MessageBox.Show (ErrorMessages.MAX_ITEMS);
        }
    }

    private void CreateFindButton()
    {
        Button newAddressButton = new Button();   
        newAddressButton.Name = buttonProperties.GetLatestRankedName();         
        newAddressButton.Content = AFindButtonsProperties.CONTENT;
        newAddressButton.Command = buttonProperties.ButtonsAction;
        UserInputGrid.Children.Add (newAddressButton);
    }

AFindButtonsProperties.cs

    public const int ROW = 0;
    public const int COLUMN = 1;
    public const double WIDTH = 30;
    public const double HEIGHT = 20;
    public const double MARGIN_INCREMENT = 22;
    public const string CONTENT = "...";
    public const string NAME = "FindAddressButton";

    public readonly VerticalAlignment verticalAlignment = VerticalAlignment.Top;
    public readonly HorizontalAlignment horizontalAlignment = HorizontalAlignment.Left;
    public readonly ICommand ButtonsAction;

    public AFindButtonsProperties (Grid inputGrid)
    {
        gridReference = inputGrid;
        int notNeeded;
        buttonReference = GetReferenceLastRankedButton (out notNeeded);
        ButtonsAction = buttonReference.Command;
    }

    private Button GetReferenceLastRankedButton (out int lastRank)
    {
        Button outputButton = null;
        int lastRankConstruction = 0;

        foreach (var element in gridReference.Children)
        {
            Button currentButton = element as Button;

            if (currentButton != null) //skipps elements that arent buttons
            {
                string[] choppedUp = currentButton.Name.ToString().Split ('_');

                if (choppedUp.Length > 1 && //prevents exception for names not following the FindButton convention.
                    choppedUp[0].Contains (NAME))
                {
                    int numberIsolated = Convert.ToInt16 (choppedUp[1]);

                    if (numberIsolated > lastRankConstruction)
                    {
                        outputButton = currentButton;
                        lastRank = numberIsolated;
                    }
                }
            }
        }

        if (outputButton == null)
        {
            throw new ViewElementNotFoundException ("Cant find any buttons in the grid reference which follow the naming convention.");
        }

        else
        {
            lastRank = lastRankConstruction;
            return outputButton;
        }
    }

    public string GetLatestRankedName()
    {
        int lastRank;
        Button lastButton = GetReferenceLastRankedButton (out lastRank);
        lastRank++;
        string name = NAME + "_" + lastRank.ToString();
        return name;
    }

【问题讨论】:

  • 所以这是一个重复的问题,但这是我的查询的答案:stackoverflow.com/questions/5102760/…
  • 如果你只是想使用点击事件,何必用这些命令!我被你的问题迷住了!
  • 因为它的摘要工具提示,我以为Command是点击事件。不过你的回答很好:)

标签: c# wpf xaml


【解决方案1】:

好的,既然你说你想要更好的做法,我把它放在这里作为答案,但要知道它并没有解决你的方法。

据我所知,您发布的代码片段需要重复多次的控件模式(即文本框和按钮)。为此,您必须使用适当的控件。此类任务的最佳选择之一是ListView

使用它的最佳方式是为每个元素创建一个模型。例如,假设您有这样的模型:

public class AModel
{
    public string Text { get; set; }
    public ICommand ClickCommand { get; set; }
} 

好吧,使用这样的模型然后我在我想使用它们的页面中创建一个ObservableCollection

public var list = new ObservableCollection<AModel>();

并使用您已有的代码向其中添加元素:

private void ClickNewBar (object sender, RoutedEventArgs e)
{
    if (list.Count < MAX_ADDRESS_BARS)
    {                
        list.Add(new AModel()
            {
                Text = "",
                ICommand = SomeCommand
            });
    }
    else
    {
        MessageBox.Show (ErrorMessages.MAX_ITEMS);
    }
}

并且知道您还有一个存储为SomeCommand 的命令。下一步是使用ListView 渲染它。为此,您需要创建一个项目模板,指定 WPF 应如何呈现列表中的每个元素。

<ListView ItemsSource={binding list}>
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid Name="UserInputGrid">               
                <TextBox Text={binding Text} />        
                <Button Command={binding ClickCommand} />
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

然后您通过将此行放在窗口构造函数中 InitializeComponents 调用下方来设置窗口的数据上下文

this.DataContext = this;

这是在 WPF 中创建动态控件的正确方法。更进一步的是使用 MVVM 并在 ViewModels 中完成工作,这是一种更好的方法。

我希望我能帮助你解决你的问题。

【讨论】:

  • 我收到错误“WPF 项目不支持绑定”。将其更改为大写 B 绑定有效吗? :S
猜你喜欢
  • 2016-01-02
  • 2018-07-24
  • 2020-10-25
  • 2023-02-04
  • 1970-01-01
  • 1970-01-01
  • 2013-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多