使用mvvm动态添加控件

时间:2016-07-17 16:03:14

标签: c# xaml

我想使用xaml创建propertygrid。扩展WPF工具包中的PropertyGrid没有自动更新,工具提示等,所以我决定创建自己的。

我的想法是创建一个ObservableCollection控件并将它们动态添加到ListBox(或ListView)。

这是一个示例项目“testy_wpf”:

要使用数据绑定,我创建一个OnPropertyChanged类

namespace testy_wpf
{
    public class NotifyPropertyChanged : INotifyPropertyChanged
    {
        public NotifyPropertyChanged ()
        {

        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(String Name)
        {
            if (PropertyChanged != null)
            {
                 PropertyChanged(this, new PropertyChangedEventArgs(Name));
            }
         }
     }
}

然后我在Test类中继承了这个类,带有一些属性(仅用于测试)

namespace testy_wpf
{
    public class Test : NotifyPropertyChanged
    {
        public Test()
        { 
        }

        private int val { get; set; }
        public int Val 
        {
            get { return val; }
            set
            {
                val = value;
                OnPropertyChanged("Val");
            }
         }

        private String name { get; set; }
        public String Name
        {
             get { return name; }
             set
             {
                  name = value;
                  OnPropertyChanged("Name");
             }
         }

        private String errorMsg { get; set; }
        public String ErrorMsg 
        {
            get {return errorMsg; }
            set 
            {
                errorMsg = value;
                OnPropertyChanged("ErrorMsg");
            }
        }

        public Control Control { get; set; }
    }
}

然后我创建一个MainWindowViewModel类

public class MainWindowViewModel
    {
        public MainWindowViewModel()
        {
            T = new ObservableCollection<Test>() 
            {
                new Test(){ Name = "Object 1" , Val = 1, Control = new TextBox(){ Text = "Test"}, ErrorMsg = "Error 1"},
                new Test(){ Name = "Object 2" , Val = 2, Control = new ComboBox(), ErrorMsg = "Error 2"},
                new Test(){ Name = "Object 3" , Val = 2, Control = new CheckBox(), ErrorMsg = "Error 3"}
            };
        }

        public ObservableCollection<Test> T { get; set; }
    };

我添加到MainWindow视图:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }
    }

在主窗口XAML中我想显示此控件。目前我创建了一些带有文本的文本框。

<Window.Resources>
    <DataTemplate x:Key="ControlTemplate">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}" Width="100"/>
            <TextBox Text="{Binding Path=Val,Mode=TwoWay,     UpdateSourceTrigger=PropertyChanged}" Width="50">
                <TextBox.ToolTip>
                    <StackPanel>
                        <TextBlock Text="{Binding ErrorMsg}" />
                    </StackPanel>
                </TextBox.ToolTip>
            </TextBox>               
        </StackPanel>
    </DataTemplate>
</Window.Resources>

<ListBox Width="200"
             HorizontalAlignment="Left"
             Margin="10"
             ItemTemplate="{StaticResource ControlTemplate}"
             ItemsSource="{Binding Path=T}" />

我的想法是使用一些contorl containter来绑定“T”(T是来自ViewModel的ObservableCollection的名称)控件属性和xaml中的一些包含。

像这样的东西

//Pseudo code
<control data="{Binding Control}" /> <!-- Where control is i.e. Textbox, ComboBox, CheckBox-->

因此,我应该有尽可能多的控件显示为T数组的长度(目前我创建TextBoxes)。稍后我将枚举someclass的所有属性以显示propertygrid字段。

我的问题是什么样的XAML包含可以存储所有类型的控件?如何将它与T数组中的某些控件绑定。

有类似的主题,但人们只创建一种控件,即文本框。而且我知道如何显示许多TextBox。

1 个答案:

答案 0 :(得分:0)

看看DataTemplateSelector。您可以提供自己的模板选择器,将特定的DataTemplate返回到ListBox(将自定义模板选择器设置为listbox的ItemTemplateSelector属性)。