菲佣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样式的调整)

 

 

 

你可能感兴趣的:(template)