2010-07-19 39 views
4

我正在開發一個WPF 4.0應用程序,我需要製作一個包含具有文本框或下拉列的列的網格,具體取決於行。例如:WPF DataGrid單列內的不同編輯控件

| Name  | Value     | Help         | 
| PROP1A | [textbox]    | Description of prop1a     | 
| Prop2A | [dropdown v]    | Description of prop2a     | 
| Prop3A | [textbox] [x checkbox] | Description of prop2a     | 
| Prop4A | [dropdown v]    | Description of prop2a     | 
| etc... 

的想法是,用戶具有他們需要輸入值的表,我們爲每個值顯示名稱和描述一起。其中一些值是需要用文本框輸入的數字,而另一些則是文本框加上覆選框,還有一些是下拉菜單。

我最初的想法是將這個基本上實現爲我將稱爲RowDescriptor的一個集合,它將指定名稱,輸入類型和幫助信息(它只是文本),然後使用綁定將集合綁定到DataGrid。基本上,這些將充當ViewModels,並且在DataGrid中設置值將通過ViewModel流向實際Model(就像MVVM應用程序的典型情況一樣)。

當我瀏覽我已有的文檔時,我找不到任何討論以這種方式動態更改列類型的方法。我現在傾向於使用網格,並手動佈置輸入(仍然使用綁定,但單獨綁定每個元素)。儘管如此,這還是需要更多的人工努力,所以我想知道是否有一種相對直接的方式來實現我的第一個想法。看起來我應該可以用DataGridTemplateColumn做些事情,但我對WPF來說比較新,我不確定我會如何去做這件事。

回答

4

您可以使用模板列來完成此操作。

這一個將顯示一個或兩個文本框,具體取決於行中的數據。

通常顯示CellTemplate,但在編輯該行時將替換爲CellEditingTemplate。

<DataGridTemplateColumn Header="Value" Width="350"> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <TextBlock 
      Text="{Binding EffectiveValue,Mode=OneWay,ValidatesOnDataErrors=True}" 
      ToolTip="{Binding EffectiveValue,Mode=OneWay}" 
      TextWrapping="Wrap" 
      /> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 

    <DataGridTemplateColumn.CellEditingTemplate> 
     <DataTemplate> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="Auto" /> 
        <ColumnDefinition Width="*" /> 
       </Grid.ColumnDefinitions> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto" /> 
        <RowDefinition Height="Auto" /> 
       </Grid.RowDefinitions> 


       <TextBlock Text="Value" Margin="4"/> 
       <TextBox 
       Grid.Column="1" 
       Text="{Binding ConfigurationValue,ValidatesOnDataErrors=True}" 
       ToolTip="{Binding ConfigurationValue}" 
       TextWrapping="Wrap" 
       AcceptsReturn="{Binding DataType, Mode=OneWay, 
            Converter={StaticResource ResourceKey=StringMatchBooleanConverter}, ConverterParameter=String}" 
       gui:FocusAttacher.Focus="True" 
       /> 

       <TextBlock Text="Default Value" Grid.Row="1" Margin="4" 
       Visibility="{Binding DefaultConfigurationValue, Converter={StaticResource ResourceKey=NullVisibilityConverter}}" 
         /> 
       <TextBox 
       Grid.Column="1" 
       Grid.Row="1" 
       Text="{Binding DefaultConfigurationValue, Mode=OneWay }" 
       ToolTip="{Binding DefaultConfigurationValue, Mode=OneWay}" 
       TextWrapping="Wrap" 
       IsReadOnly="True" 
       Visibility="{Binding DefaultConfigurationValue, Converter={StaticResource ResourceKey=NullVisibilityConverter}}" 

       /> 

      </Grid> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellEditingTemplate> 
</DataGridTemplateColumn> 
+0

這基本上是一個Cory Larson的方法的WPF版本,在那裏你有行中的所有類型,然後顯示或隱藏適當的類型,對不對? (不同的是,在你的例子中,這是通過綁定完成的,對嗎?) – notJim 2010-07-19 01:30:15

+0

我沒有機會看他的代碼。這在我心中是新鮮的,因爲我不到一週前就知道如何去做。 – 2010-07-19 06:30:00

1

我不得不在一個帶有GridView的ASP.NET應用程序中這樣做一次,雖然它是一種不同的技術,但我認爲答案是一樣的。我所要做的只是在每個單元格中添加所有不同類型的控件,但最初不能看到它們。

然後,您可以重寫在每個項綁定到網格中的行後觸發的任何事件(我也是WPF的新手,我不確定事件是什麼),更改適當的可見性控制單元中的任何信息,這些信息基於您在綁定該行的對象中知道的任何信息,然後將該控件填充或綁定到適當的值。

當你需要將值返回時,確實會變得更有趣,但我想我最終搜索了可見的控件,然後根據控件的類型做出決定。我認爲這是你能夠完成它的唯一方法,因爲我從Microsoft使用的每個網格控件似乎都假設你的列永遠不需要不同類型的控件。

我在SO上問過幾乎相同的問題。這是the post。也許它會讓你的球滾動。