在使用DataGrid的時候,有時候需要使某些列為ComboBox,這時自然想到使用DataGridComboBoxColumn,但是如果使用的是ItemsSource數據綁定后台的對象,就會發現,這根本就不能用。
首先,看有問題的代碼:

1 using System.Windows; 2 using System.Collections.ObjectModel; 3 using System.ComponentModel; 4 5 namespace WPFTest 6 { 7 /// <summary> 8 /// 數據項 9 /// </summary> 10 public class DataItem 11 { 12 public int Value { get; set; } 13 public DataItem(int val) { Value = val; } 14 } 15 /// <summary> 16 /// MainWindow.xaml 的交互邏輯 17 /// </summary> 18 public partial class MainWindow : Window 19 { 20 public MainWindow() 21 { 22 InitializeComponent(); 23 // 選中數據 24 SelectedList.Add(new DataItem(1)); SelectedList.Add(new DataItem(2)); 25 // 可選數據 26 SelectionList.Add(1); SelectionList.Add(2); SelectionList.Add(3); 27 } 28 29 /// <summary> 30 /// 選中的數據列表 31 /// </summary> 32 public ObservableCollection<DataItem> SelectedList 33 { 34 get { return _selectedList; } 35 set { _selectedList = value; } 36 } 37 private ObservableCollection<DataItem> _selectedList = new ObservableCollection<DataItem>(); 38 39 /// <summary> 40 /// 可供選擇的數據列表 41 /// </summary> 42 public ObservableCollection<int> SelectionList 43 { 44 get { return _selectionList; } 45 set { _selectionList = value; } 46 } 47 private ObservableCollection<int> _selectionList = new ObservableCollection<int>(); 48 49 // 顯示選中的 50 private void Button_Click(object sender, RoutedEventArgs e) 51 { 52 TBX_Selected.Text = ""; 53 foreach (var item in SelectedList) 54 TBX_Selected.Text += item.Value.ToString(" --->0<--- "); 55 } 56 57 } 58 }
前台為:
1 <Window x:Class="WPFTest.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPFTest" Name="this" Height="350" Width="525"> 5 <StackPanel> 6 <DataGrid ItemsSource="{Binding Path=SelectedList,ElementName=this}" AutoGenerateColumns="False"> 7 <DataGrid.Columns> 8 <DataGridTextColumn Header="文本模式" Binding="{Binding Path=Value}" /> 9 <DataGridComboBoxColumn Header="ComboBox模式" 10 SelectedValueBinding="{Binding Path=Value}" 11 ItemsSource="{Binding Path=SelectionList,ElementName=this}" /> 12 </DataGrid.Columns> 13 </DataGrid> 14 <Button Content="觀察選中的數據" Click="Button_Click" Margin="10"/> 15 <TextBox Name="TBX_Selected" /> 16 </StackPanel> 17 </Window>
在這里通過把Window控件的Name設置為this,然后在綁定的時候指定ElementName=this及Path屬性來關聯到后台數據源。為了測試是否有效,我還定義了一個TextBox來顯示SelectedList中的數據的值。首先,可以肯定的是,用DataGridTextColumn一點問題也沒有,數據可以正常地顯示和更新,但是使用DataGridComboBoxColumn時問題就出現了,數據不能顯示,就像什么都沒有綁定上去一樣:
我在網上找了下資料,都與MSDN上的例子相似,DataGridComboBoxColumn對數據源有下面的要求:
使用下列選項之一,若要填充下拉列表,首先設置 ComboBox 的 ItemsSource 屬性:
1、靜態資源。有關更多信息,請參見 StaticResource 標記擴展。
2、x: 靜態代碼實體。有關更多信息,請參見 x:Static 標記擴展。
3、ComboBoxItem 類型的內聯集合。
於是,試試DataGridTemplateColumn來做ComboBox:
1 <DataGridTemplateColumn Header="Template模式"> 2 <DataGridTemplateColumn.CellTemplate> 3 <DataTemplate> 4 <ComboBox SelectedValue="{Binding Path=Value}" ItemsSource="{Binding Path=SelectionList,ElementName=this}" /> 5 </DataTemplate> 6 </DataGridTemplateColumn.CellTemplate> 7 </DataGridTemplateColumn>
運行發現,顯示是正常了,但是不論我怎么改,SelectedList中的數據都不帶改變,我嘗試設置了ComboBox的各項屬性,也沒有成功。但是非常奇怪的地方是,如果在選擇后,去點了上面的DataGridComboBoxColumn ,數據就能正常正同步過去:
我想這可能是DataGridComboBoxColumn在選擇后會觸發一個事件,完成同步工作。
好了,這樣還是不行,我去了stackoverflow上找資料,問題終於得到了解決。基本上原因是這樣的:DataGrid的列並沒有數據上下文,所以DataGridTemplateColumn中的ComoBox從未添加到“Visual Tree(可視化樹)”中。只要Grid繪制了單元,並且得到了數據上下文后,就能正常地使用ItemsSource屬性來完成綁定了。修正后的代碼:
1 <DataGridComboBoxColumn Header="ComboBox模式(修正)"> 2 <DataGridComboBoxColumn.EditingElementStyle> 3 <Style TargetType="ComboBox"> 4 <Setter Property="ItemsSource" Value="{Binding Path=SelectionList,ElementName=this}" /> 5 <Setter Property="SelectedValue" Value="{Binding Path=Value}" /> 6 </Style> 7 </DataGridComboBoxColumn.EditingElementStyle> 8 </DataGridComboBoxColumn>
這樣,數據能夠正常地同步了,但是如果不點中對應單元格,ComboBox就不會顯示出來,只有點中了才顯示,繼續參考資料,問題原因是上面只設置了EditingElementStyle(編輯時樣式),所以在選中編輯時就會出現ComboBox,要想一直顯示,還得設置ElementStyle,使它和EditingElementStyle一樣就行了:
<DataGridComboBoxColumn.ElementStyle> <Style TargetType="ComboBox"> <Setter Property="ItemsSource" Value="{Binding Path=SelectionList,ElementName=this}" /> <Setter Property="SelectedValue" Value="{Binding Path=Value}" /> </Style> </DataGridComboBoxColumn.ElementStyle>
問題圓滿解決,其實也不難,只是不知道,沒想到而已,大家可以看看。
好多人在評論里要DEMO,我沒有時間去一個一個發,直接就把前面例子的DEMO放這了,大家自行下載吧!
轉載請注明原址:http://www.cnblogs.com/lekko/archive/2012/11/23/2784789.html