2011-02-19 64 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}"/>