9

我在 WPF 中工作——在我的应用程序中有buttonwith 。click event handler当我单击按钮时,它的事件处理程序会在网格中生成一个名为grids. 在这个新行中,我想以编程方式添加另一个网格,以在行中的这个网格中添加标签、按钮和文本框。当我执行我的代码时,它只生成一个texboxes!标签和按钮显示一次!这里的代码和图像是:如果我的查询不清楚,请随时询问!

 int r =0;
 private void button2_Click(object sender, RoutedEventArgs e)
    {
        TextEdit text1; Button button1; Grid grid1;
        grids.RowDefinitions.Add(new RowDefinition());
        text1 = new TextEdit();
        text1.SetValue(Grid.ColumnProperty, 1);
        text1.SetValue(Grid.RowProperty, r);
        button1 = new Button();
        button1.Content = "Left + " + r;
        button1.Click += new RoutedEventHandler(button1_Click);
        button1.SetValue(Grid.ColumnProperty, 1);
        button1.SetValue(Grid.RowProperty, r);
        grid1 = new Grid();
        grid1.SetValue(Grid.ColumnProperty, 1);
        grids.RowDefinitions.Add(new RowDefinition());
        grid1.SetValue(Grid.RowProperty, r);
        grids.Children.Add(button1);
        grids.Children.Add(text1);
        r = r + 1;
    }

在此处输入图像描述 编辑

 int r =0;
 private void button2_Click(object sender, RoutedEventArgs e)
  {
    db obj = new db();
    var query = from p in obj.TableA select p ;

  foreach(var a in query.ToList())
  {
    TextEdit text1; Button button1; Grid grid1;
    grids.RowDefinitions.Add(new RowDefinition());
    text1 = new TextEdit();
    text1.SetValue(Grid.ColumnProperty, 1);
    text1.SetValue(Grid.RowProperty, r);
    button1 = new Button();
    button1.Content = a.name;
    button1.Click += new RoutedEventHandler(button1_Click);
    button1.SetValue(Grid.ColumnProperty, 1);
    button1.SetValue(Grid.RowProperty, r);
    grid1 = new Grid();
    grid1.SetValue(Grid.ColumnProperty, 1);
    grids.RowDefinitions.Add(new RowDefinition());
    grid1.SetValue(Grid.RowProperty, r);
    grids.Children.Add(button1);
    grids.Children.Add(text1);
    r = r + 1;}
}
4

2 回答 2

26

行。删除所有代码并重新开始。

如果您正在使用 WPF,那么您确实需要具备WPF 心态

作为一般规则,您几乎从不在 WPF 的过程代码中创建或操作 UI 元素。这就是 XAML 的用途。

这是在 WPF 中执行您所要求的正确方法(在一个完整的工作示例中):

<Window x:Class="MiscSamples.ItemsControlSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
        Title="ItemsControlSample" Height="300" Width="300">
    <DockPanel>
        <Button Content="Add New Row" Command="{Binding AddNewRowCommand}"
                DockPanel.Dock="Bottom"/>

        <ItemsControl ItemsSource="{Binding Data}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border  BorderBrush="Black" Background="Gainsboro" BorderThickness="1" Margin="2">
                        <!-- This is the Inner Grid for each element, which is represented in Brown color in your picture -->
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>

                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition Width=".2*"/>
                                <ColumnDefinition Width=".2*"/>
                            </Grid.ColumnDefinitions>

                            <Label Content="{Binding Label1Text}"
                                   Margin="2"/>

                            <Button Content="Button1" 
                                    Command="{Binding DataContext.Command1, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
                                    CommandParameter="{Binding}"
                                    Grid.Column="1" Margin="2"/>

                            <Button Content="Button2" 
                                    Command="{Binding DataContext.Command2, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
                                    CommandParameter="{Binding}"
                                    Grid.Column="2" Margin="2"/>

                            <dxe:TextEdit Text="{Binding Text}"
                                          Grid.Row="1" Grid.ColumnSpan="3"
                                          Margin="2"/>
                        </Grid>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>

            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <ScrollViewer CanContentScroll="True">
                        <ItemsPresenter/>
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>

            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </DockPanel>
</Window>

代码背后:

public partial class ItemsControlSample : Window
{
    public ItemsControlSample()
    {
        InitializeComponent();
        DataContext = new ItemsControlSampleViewModel();
    }
}

视图模型:

public class ItemsControlSampleViewModel
{
    public ObservableCollection<ItemsControlSampleData> Data { get; set; }

    public Command AddNewRowCommand { get; set; }

    public Command<ItemsControlSampleData> Command1 { get; set; }

    public Command<ItemsControlSampleData> Command2 { get; set; }

    public ItemsControlSampleViewModel()
    {
        var sampledata = Enumerable.Range(0, 10)
                                   .Select(x => new ItemsControlSampleData()
                                                {
                                                    Label1Text = "Label1 " + x.ToString(),
                                                    Text = "Text" + x.ToString()
                                                });

        Data = new ObservableCollection<ItemsControlSampleData>(sampledata);
        AddNewRowCommand = new Command(AddNewRow);
        Command1 = new Command<ItemsControlSampleData>(ExecuteCommand1);
        Command2 = new Command<ItemsControlSampleData>(ExecuteCommand2);

    }

    private void AddNewRow()
    {
        Data.Add(new ItemsControlSampleData() {Label1Text = "Label 1 - New Row", Text = "New Row Text"});
    }

    private void ExecuteCommand1(ItemsControlSampleData data)
    {
        MessageBox.Show("Command1 - " + data.Label1Text);
    }

    private void ExecuteCommand2(ItemsControlSampleData data)
    {
        MessageBox.Show("Command2 - " + data.Label1Text);
    }
}

数据项:

public class ItemsControlSampleData
{
    public string Label1Text { get; set; }

    public string Text { get; set; }
}

助手类:

public class Command : ICommand
{
    public Action Action { get; set; }

    public string DisplayName { get; set; }

    public void Execute(object parameter)
    {
        if (Action != null)
            Action();
    }

    public bool CanExecute(object parameter)
    {
        return IsEnabled;
    }

    private bool _isEnabled = true;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set
        {
            _isEnabled = value;
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
        }
    }

    public event EventHandler CanExecuteChanged;

    public Command(Action action)
    {
        Action = action;
    }
}

public class Command<T>: ICommand
{
    public Action<T> Action { get; set; }

    public void Execute(object parameter)
    {
        if (Action != null && parameter is T)
            Action((T)parameter);
    }

    public bool CanExecute(object parameter)
    {
        return IsEnabled;
    }

    private bool _isEnabled = true;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set
        {
            _isEnabled = value;
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
        }
    }

    public event EventHandler CanExecuteChanged;

    public Command(Action<T> action)
    {
        Action = action;
    }
}

结果:

在此处输入图像描述

  • 请注意,我不是在过程代码中处理 UI,而是使用DataBinding简单、简单的属性。这就是您在 WPF 中编程的方式。这就是 WPF 的心态。
  • 我正在使用 XAML 中定义的ItemsControlDataTemplate让 WPF 为我的每个数据项创建 UI。
  • 还要注意我的代码除了公开数据和定义可重用的命令之外什么都不做,这些命令用作对用户操作(如按钮单击)的抽象。通过这种方式,您可以专注于编写业务逻辑,而不是为如何使 UI 工作而苦苦挣扎。
  • 每个项目内的按钮都使用相对源绑定绑定到命令,以便在可视树中向上导航并找到 ItemsControl 的 DataContext,其中实际定义了命令。
  • 当您需要添加新项目时,您只需向ObservableCollection包含您的数据的新项目添加一个新项目,WPF 会自动创建绑定到该项目的新 UI 元素。
  • 尽管这看起来像是“代码过多”,但我在此处发布的大部分代码都具有高度可重用性,并且可以在通用ViewModel<T>中实现,然后可重用于任何类型的数据项。Command并且Command<T>也是可在任何 MVVM 框架(如PrismMVVM LightCaliburn.Micro )中找到的一次性可重用类。
  • 这种方法在 WPF 中非常受欢迎,因为它可以在 UI 和业务逻辑之间实现大量的可伸缩性和独立性,并且还可以实现 ViewModel 的可测试性。
  • 我建议您阅读帖子中链接的所有材料,最重要的是 Rachel 的 WPF Mentality 和相关博客文章。如果您需要进一步的帮助,请告诉我。
  • WPF 摇滚。只需将我的代码复制并粘贴到 a 中File -> New Project -> WPF Application,然后自己查看结果。
于 2013-09-29T23:16:26.870 回答
8

实际上,在后面的代码中比在 xaml 代码中要容易得多。

我的 Xaml 代码:

<Window x:Class="WpfAddGridWithStackPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
        <Grid>
        <Grid x:Name="Grid_Grid" Margin="0,0,0,32">

        <Grid>
    <ScrollViewer VerticalScrollBarVisibility="Auto">
        <Grid x:Name="Grid_Grid" Margin="0,0,0,32"/>
    </ScrollViewer>
    <Button x:Name="btn_Add" Height="32" DockPanel.Dock="Bottom" VerticalAlignment="Bottom" Content="Add New Row" Click="btn_Add_Click" Width="150" HorizontalAlignment="Left" UseLayoutRounding="True" />
    <Button x:Name="btn_Remove" Height="32" DockPanel.Dock="Bottom" VerticalAlignment="Bottom" Content="Remove last Row" Click="btn_Remove_Click" Width="150" HorizontalAlignment="Right" />
</Grid>
</Window>

和背后的代码:

public partial class MainWindow : Window
    {
        int num = 0;
        public MainWindow()
        {
            InitializeComponent();
        }

        void btn1_Click(object sender, RoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        void btn2_Click(object sender, RoutedEventArgs e)
        {
            throw new NotImplementedException();
        }

        private void btn_Remove_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Grid_Grid.RowDefinitions.RemoveAt(Grid_Grid.RowDefinitions.Count - 1);
                Grid_Grid.Children.RemoveAt(Grid_Grid.Children.Count - 1);
                num--;
            }
            catch { }
        }

        private void btn_Add_Click(object sender, RoutedEventArgs e)
        {
            StackPanel stack = new StackPanel();
            DockPanel dock = new DockPanel();
            Label lbl = new Label();
            Button btn1 = new Button();
            Button btn2 = new Button();
            TextBox txt1 = new TextBox();

            stack.Children.Add(dock);
            stack.Children.Add(txt1);
            dock.Children.Add(lbl);
            dock.Children.Add(btn2);
            dock.Children.Add(btn1);

            #region StackPanel Properties
            stack.Background = Brushes.LightGray;
            #endregion

            #region DockPanel Content Properties
            lbl.Content = "Label " + (num + 1).ToString();
            lbl.Height = 32;
            lbl.Width = 100;
            lbl.FontSize = 12;
            lbl.SetValue(DockPanel.DockProperty, Dock.Left);
            lbl.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;

            btn1.Content = "Butten 1";
            btn1.Height = 32;
            btn1.Width = 100;
            btn1.FontSize = 12;
            btn1.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
            btn1.SetValue(DockPanel.DockProperty, Dock.Right);
            btn1.Click += new RoutedEventHandler(btn1_Click);

            btn2.Content = "Butten 2";
            btn2.Height = 32;
            btn2.Width = 100;
            btn2.FontSize = 12;
            btn2.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
            btn2.SetValue(DockPanel.DockProperty, Dock.Right);
            btn2.Click += new RoutedEventHandler(btn2_Click);
            #endregion

            #region TextBox Properties
            txt1.Text = "Text " + (num + 1).ToString();
            txt1.Height = 32;
            txt1.Width = double.NaN;
            txt1.FontSize = 12;
            txt1.Padding = new Thickness(0, 7, 0, 7);
            #endregion

            Grid_Grid.RowDefinitions.Add(new RowDefinition());
            Grid_Grid.RowDefinitions[num].Height = new GridLength(66, GridUnitType.Pixel);
            Grid_Grid.Children.Add(stack);
            stack.SetValue(Grid.RowProperty, num);
            num++;
        }
    }
于 2015-01-03T14:49:19.537 回答