2011-02-19 32 views
0

我正在为数据库迁移做一个应用程序。我用WPF GUI制作了一个多线程框架。我把成才像这样在我的命名空间/文件夹:WPF“部分形式”

class Something : Migrator { 
    public override Run(){ 
     //I would need this 
     string valueOfMyCustomFieldOnForm = xyz.Text; //example 

     int count = 500; 
     for(int i = 0; i < 500; i++){ 
      //do something here 
      OnProgressChanged(...); //call event, GUI is updated 
     } 
     OnCompleted(...); //migration completed 
    } 
} 

然后使用反射,我把所有的类在命名空间在下拉列表中。当我在列表中选择一个并单击“开始”时,将启动Run方法中带有代码的线程。

DB Host: TEXTBOX 
DB Username: TEXTBOX 
DB Password: TEXTBOX 
-- 
Migrator custom field 1: TEXTBOX 
Migrator custom field 2: TEXTBOX 
... 
-- 
List with migrated items - irrelevant 

GUI上很少有commong字段(如数据库主机,用户名等)。但对于其中一些迁移者,我需要GUI上的自定义字段(例如3个额外的文本框字段)。 什么是在WPF中做到这一点的最佳方式?我需要GUI的一部分是动态的。

回答

2

在你的问题中有很多看似不相关的信息,我认为这实际上是关于在WPF中创建元数据驱动UI的机制。下面是解决这个问题的一种方法:

假设你想要构建一个类似于表单的用户界面:一个为每个属性显示一行,并带有某种提示和输入控件的网格。为此,您将需要一组对象,集合中的每个项目都包含描述属性及其值的属性。一个简单的设计将是一个暴露Prompt属性和Value属性并实现更改通知的类。

一旦你已经创建并填充此集合,你可以实现其显示在网格中ItemsControl

<ItemsControl ItemsSource="{Binding Properties}" Grid.IsSharedSizeScope="True"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate DataType="PropertyViewModel"> 
     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition SharedSizeGroup="Prompt"/> 
       <ColumnDefinition SharedSizeGroup="Value"/>     
      </Grid.ColumnDefinition> 
      <Grid.RowDefinitions> 
       <RowDefinition/> 
      </Grid.RowDefinitions> 
     </Grid> 
     <Label Content="{Binding Prompt}"/> 
     <TextBox Grid.Column="1" Text="{Binding Value, Mode=TwoWay}"/> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

这很简单 - 它是最复杂的是使用Grid.IsSharedSizeScope使所有的该控件创建的网格使用相同的列宽。您也可以使用ListView而不是ItemsControl,但使用ListView这会引入一系列与焦点和选择有关的问题,而您可能不想处理这些问题。

注意的,因为这是WPF模板匹配的魔力,你可以想见,实现Value属性作为object,并建立不同的模板来处理不同的可能类型Value财产 - 就像一个真正的属性表一样。要做到这一点,你需要创建一个模板,为每种类型的,如:

<DataTemplate DataType="{x:Type System:String}"> 
    <TextBox Text="{Binding Value, Mode=TwoWay}"/> 
</DataTemplate> 
<DataTemplate DataType="{x:Type System:DateTime}"> 
    <DatePicker Value="{Binding Value, Mode=TwoWay}"/> 
</DataTemplate> 

等,然后你会更改PropertyViewModel的模板,以便而不是显示在TextBoxValue的,它采用了ContentPresenter ,例如:

<ContentPresenter Grid.Column="1" Content="{Binding}"/>