zoukankan      html  css  js  c++  java
  • 菲佣WPF——4(关于DataTemplate(2)动态控件添加神器)

    动态控件添加,基本UI开发都需要使用。我看过很多人写,都停留在WinFrom开发时代的直接操作控件来实现动态添加控件。到了WPF依然很多人在这样操作。

    (不是说这样写错误,但是这违背了UI和逻辑分离的思想,不利于后期维护。深有体会。当看到后台密密麻麻的添加子控件,心情瞬间崩溃)

    我们先来看下UI和逻辑不分离的代码(简单粗暴实现代码):

    XAML代码:

    <Window x:Class="WpfApplication4.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:local="clr-namespace:WpfApplication4"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="60"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Button Content="Add" Width="50" Grid.Row="0" Click="Button_Click_1" />
            <WrapPanel x:Name="wpContainer" Width="525" Height="300" Grid.Row="1"/>
        </Grid>
    </Window>

    XAML.cs代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace WpfApplication4
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            #region << Constructor >>
            public MainWindow()
            {
                InitializeComponent();
                //this.DataContext = new MainWindowsViewModel();
            }
            #endregion
    
            #region << Method >>
            private void Button_Click_1(object sender, RoutedEventArgs e)
            {
                this.wpContainer.Children.Add(GetChild("NewChild"));
            }
    
            private StackPanel GetChild(string name)
            {
                StackPanel container = new StackPanel();
                container.Width = 300;
                container.Orientation = Orientation.Horizontal;
    
                TextBlock tb = new TextBlock();
                tb.Width = 120;
                tb.Height = 60;
                tb.Margin = new Thickness(4, 4, 4, 4);
                tb.Text = name;
    
                Button btnRead = new Button();
                btnRead.Content = "Read";
                btnRead.Width = 80;
                btnRead.Height = 60;
                btnRead.Margin = new Thickness(4, 4, 4, 4);
    
                Button btnWrite = new Button();
                btnWrite.Content = "Write";
                btnWrite.Width = 80;
                btnWrite.Height = 60;
                btnWrite.Margin = new Thickness(4, 4, 4, 4);
    
                container.Children.Add(tb);
                container.Children.Add(btnRead);
                container.Children.Add(btnWrite);
    
                return container;
    
            }
            #endregion
        }
    }

    上面的实现动态添加控件。我直接使用路由事件(我可不想把控件传到ViewModel中,所以没用Command)
    只是简单的添加,不调整布局,无样式。就有许多代码了。当我们动态添加的控件过于复杂。或者前台美工想调整布局。觉得是灾难;

    下面是我们使用下DataTemplate的动态添加控件。(容器使用ListView.容器样式默认(只是为了实现动态,不关心样式))

    XAML代码:

    <Window x:Class="WpfApplication4.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:local="clr-namespace:WpfApplication4"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <DataTemplate x:Key="itemTemplate">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="NewChild" Width="120" Height="60" Margin="4,4,4,4"/>
                    <Button Content="Read" Width="80" Height="60" Margin="4,4,4,4"/>
                    <Button Content="Write" Width="80" Height="60" Margin="4,4,4,4"/>
                </StackPanel>
            </DataTemplate>
        </Window.Resources>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="60"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Button Content="Add" Width="50" Grid.Row="0" Command="{Binding ClickCommand}"/>
            <ListView x:Name="wpContainer" Width="525" Height="300" Grid.Row="1" ItemTemplate="{StaticResource ResourceKey=itemTemplate}" ItemsSource="{Binding ItemList}" />
        </Grid>
    </Window>

    XAML.cs代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace WpfApplication4
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            #region << Constructor >>
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = new MainWindowsViewModel();
            }
            #endregion
        }
    }

    后台代码很干净

    ViewModel代码:

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    
    namespace WpfApplication4
    {
        public class MainWindowsViewModel:NotifyObject
        {
            #region << Property >>
            public ObservableCollection<string> ItemList
            {
                get;
                set;
            }
            public ICommand ClickCommand { get; set; }
            #endregion
            #region << Constructor >>
            public MainWindowsViewModel()
            {
                ItemList = new ObservableCollection<string>();
                ClickCommand = new DeletegateCommand(Click);
            }
            #endregion
    
            #region << Method >>
            public void Click()
            {
                ItemList.Add("xx");
            }
            #endregion
    
        }
    }

    ViewModel代码也很干净。

    相对来说,很多的代码都移到了前台页面中。所有逻辑层的代码相对来说较少。

    动态添加 只要有ItemTemplate属性的控件都可以使用。(基本上)

    这样写的话,主要任务就交给了美观(LIstView样式的调整)

  • 相关阅读:
    【bzoj1300】大数计算器
    BZOJ3192: [JLOI2013]删除物品
    BZOJ2818: Gcd
    BZOJ2440: [中山市选2011]完全平方数
    BZOJ3994: [SDOI2015]约数个数和
    BZOJ2154: Crash的数字表格
    BZOJ3529: [Sdoi2014]数表
    BZOJ2301: [HAOI2011]Problem b
    BZOJ1562: [NOI2009]变换序列
    BZOJ1059: [ZJOI2007]矩阵游戏
  • 原文地址:https://www.cnblogs.com/qiurideyun/p/2912810.html
Copyright © 2011-2022 走看看