【问题标题】:Add controls dynamically using mvvm使用 mvvm 动态添加控件
【发布时间】:2016-07-17 16:03:14
【问题描述】:

我想使用 xaml 制作属性网格。 Extended WPF Toolkit 中的 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 容器将“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 数组中的一些控件绑定。

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

【问题讨论】:

    标签: c# xaml


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多