【问题标题】:How to Programmatically create Grid within row of a Grid in Wpf如何以编程方式在 Wpf 中的网格行内创建网格
【发布时间】:2013-10-05 12:39:59
【问题描述】:

我在 WPF 中工作——我的应用程序中有 buttonclick 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;}
}

【问题讨论】:

  • 你应该使用StackPanel而不是Grid作为外部布局
  • @Anirudh 好的,谢谢,我应该在 grid1 中添加这个堆栈面板吗?
  • 名称为grids 的网格应该是stackpanel,它将包含所有网格..
  • 网格中不能嵌套网格吗
  • @GeorgianBrit 然后怎么办:(

标签: c# .net wpf


【解决方案1】:

在后台代码中实际上比在 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++;
        }
    }

【讨论】:

    【解决方案2】:

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

    如果你正在使用 WPF,你真的需要The WPF Mentality

    作为一般规则,您几乎从不在 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。
    • 还要注意我的代码除了公开数据和定义可重用的Commands 之外什么都不做,这些Commands 用作对用户操作(例如按钮单击)的抽象。这样一来,您就可以专注于编写业务逻辑,而不是纠结于如何让 UI 正常工作。
    • 每个项目内的按钮都使用RelativeSource 绑定绑定到命令,以便在可视树中向上导航并找到 ItemsControl 的 DataContext,其中实际定义了命令。
    • 当您需要添加新项目时,只需将新项目添加到包含您的数据的 ObservableCollection,WPF 就会自动创建绑定到该项目的新 UI 元素。
    • 虽然这看起来像是“代码过多”,但我在此处发布的大部分代码都是高度可重用的,并且可以在通用ViewModel&lt;T&gt; 中实现,然后可重用于任何类型的数据项。 CommandCommand&lt;T&gt; 也是一次性可重用类,可以在任何 MVVM 框架中找到,例如 PrismMVVM LightCaliburn.Micro
    • 这种方法在 WPF 中非常受欢迎,因为它在 UI 和业务逻辑之间实现了极大的可扩展性和独立性,并且还实现了 ViewModel 的可测试性。
    • 我建议您阅读帖子中链接的所有材料,最重要的是 Rachel 的 WPF Mentality 和相关博客文章。如果您需要进一步的帮助,请告诉我。
    • WPF 摇滚。只需将我的代码复制并粘贴到 File -&gt; New Project -&gt; WPF Application 中,然后自己查看结果。

    【讨论】:

    • 高核心!不使用 MVVM 是否可以做到这一点?
    • @tameenmalik 你为什么要这样做? MVVM 与 WPF 密切相关。做非 MVVM WPF 真的是在寻找不必要的麻烦。
    • 是的 HighCore 你是对的 :) 。 . .但实际上我想要这个:(:)
    • @Tameenmalik 恐怕我无法为您提供帮助。编写不必要的、丑陋的、不可维护的代码不是我的专长。
    • 这很漂亮。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多