C# WPF host computer development (dynamically adding controls)

[Disclaimer: All rights reserved. Reprinting is welcome. Please do not use it for commercial purposes. Contact email: [email protected]]

        When writing graphical interface software, we often encounter a situation. That is, the controls displayed on the graphical interface may be variable. There may be more or less. The specific amount of content displayed depends on the configuration file. This is actually a bit embarrassing for us. After all, in most scenarios, after the software is opened, where and what content is configured has already been determined.

        But it doesn’t matter, c# wpf also takes this into consideration, and we can flexibly add and set it by writing code. After all, all that is left in the xaml file is an empty grid interface.

1.xaml interface design

        The xaml interface is relatively simple. For the convenience of display, we designed two lines. The height of the first row is 100, and the remaining space is reserved for the second row. In order to place the controls, this grid was specially named mainGrid.

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="600">
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="100" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid  Grid.Row="1" x:Name="mainGrid">
            <!-- Add your own layout here -->
        </Grid>
    </Grid>
</Window>

2. Initialize button

        ​​ ​​This case is just to demonstrate how to add controls. The added content is relatively small, just a button. First initialize the button and set the button's properties, which are content, width and height. At the same time, a callback function is configured for this button. After the button is set, create a stack panel and install the button in this stack panel. The last and most important step is to save the stack panel into the space of the mainGrid, thus realizing the entire interface.

        public MainWindow()
        {
            InitializeComponent();
            AddButtonDynamically();
        }

        private void AddButtonDynamically()
        {
            // 创建一个新的Button控件
            Button newButton = new Button();

            // 设置Button的属性
            newButton.Content = "Click me!";
            newButton.Width = 100;
            newButton.Height = 100;

            // 为Button添加Click事件处理程序
            newButton.Click += NewButton_Click;

            // 创建一个StackPanel并将Button添加到其中
            StackPanel stackPanel = new StackPanel();
            stackPanel.Children.Add(newButton);

            // 将StackPanel添加到窗口中的Grid中
            mainGrid.Children.Add(stackPanel);
        }

        The button callback function is as follows,

        // Click事件处理程序
        private void NewButton_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button Clicked!");
        }

3. Update interface in multi-threads

        In addition to dynamically adding space, another part to pay attention to is the update of the interface part and multi-threading. Starting a thread is very simple, but if you update the interface in a new thread, you need to pay attention to this. In order to illustrate this problem, we update the interface below,

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="600">
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="100" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Label x:Name="text" Grid.Row="0" Content="0" HorizontalAlignment="Center">
        </Label>
        <Grid  Grid.Row="1" x:Name="mainGrid">
            <!-- Add your own layout here -->
        </Grid>
    </Grid>
</Window>

        The difference between this interface and the previous one is that there is an extra Label, which is placed in row 0 and named text. To analyze multi-threading, first we add a multi-threading library,

using System.Threading;

        After adding it, you can create a thread and start the thread. Generally, each thread has a corresponding thread entry function.

        public MainWindow()
        {
            InitializeComponent();
            AddButtonDynamically();

            Thread newThread = new Thread(new ThreadStart(ThreadMethod));
            newThread.Start();
        }

        private void ThreadMethod()
        {
            int cnt = 0;

            while(true)
            {
                cnt += 1;
                Dispatcher.Invoke(() =>
                {
                    // 在UI线程上执行操作(如果需要)
                    text.Content = Convert.ToString(cnt);
                });

                Thread.Sleep(1000);
            }
        }

        Multi-threaded operations are normal. What needs attention here is the text update part. In other words, if you need to update the content of the interface, it is best to use the Dispatcher.Invoke() method.

Guess you like

Origin blog.csdn.net/feixiaoxing/article/details/134997201