如何在Wpf中以编程方式在网格的行内创建网格

Tam*_*lik 9 .net c# wpf

我在WPF的工作-有一个buttonclick event handler我的应用程序.当我点击按钮时,它的事件处理程序在网格中生成一个名为as的新行grids.在这个新的行中,我想以编程方式添加另一个网格,以便在此行的网格中添加Label,Button和TextBox.当我执行我的代码时,它只生成一个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;
    }
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述 编辑

 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;}
}
Run Code Online (Sandbox Code Playgroud)

Fed*_*gui 24

好.删除所有代码并从头开始.

如果你正在使用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>
Run Code Online (Sandbox Code Playgroud)

代码背后:

public partial class ItemsControlSample : Window
{
    public ItemsControlSample()
    {
        InitializeComponent();
        DataContext = new ItemsControlSampleViewModel();
    }
}
Run Code Online (Sandbox Code Playgroud)

视图模型:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

数据项:

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

    public string Text { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

助手班:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述

  • 请注意我不是在处理程序代码中处理UI,而是使用DataBinding简单,简单的属性.这就是你在WPF中编程的方式.这就是WPF的心态.
  • 我正在使用在XAML中定义的ItemsControlDataTemplate来让WPF为我的每个数据项创建UI.
  • 还要注意我的代码除了公开数据和定义可重用的命令之外什么都不做,这些命令用作用户操作(如Button点击)的抽象.通过这种方式,您可以专注于编写业务逻辑,而不是如何使UI工作.
  • 每个项目中的按钮都使用RelativeSource Binding绑定到命令,以在Visual Tree中向上导航,并找到ItemsControl的DataContext,其中实际定义了命令.
  • 当您需要添加新项目时,只需向ObservableCollection包含数据的项目添加新项目,WPF会自动创建绑定到该项目的新UI元素.
  • 虽然这可能看起来像"太多代码",但我在这里发布的大多数代码都是高度可重用的,并且可以在Generic ViewModel<T>中实现,然后可以为任何类型的数据项重用.Command并且Command<T>也是可写入的可重用类,可以在任何MVVM框架中找到,例如Prism,MVVM LightCaliburn.Micro.
  • 这种方法在WPF中非常受欢迎,因为它在UI和业务逻辑之间实现了大量的可伸缩性和独立性,并且还实现了ViewModel的可测试性.
  • 我建议你阅读帖子中链接的所有资料,最重要的是Rachel的WPF Mentality和相关的博客文章.如果您需要进一步的帮助,请告诉我.
  • WPF Rocks.只需复制并粘贴我的代码,File -> New Project -> WPF Application然后自己查看结果.

  • @Tameenmalik我担心我无法帮助你.编写不必要的,丑陋的,不可维护的代码不是我的领域. (4认同)
  • @tameenmalik为什么要这么做?MVVM与WPF并驾齐驱。做非MVVM WPF确实在寻找不必要的麻烦。 (2认同)

Arc*_*gel 7

在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>
Run Code Online (Sandbox Code Playgroud)

和代码背后:

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++;
        }
    }
Run Code Online (Sandbox Code Playgroud)