• WPF使用DataGridComboBoxColumn完成绑定


      在使用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 属性:

      于是,试试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 

  • 相关阅读:
    Centos 端口开放 Firewall
    windows 命令
    macOS 提示已损坏无法打开解决办法
    Linux screen
    pixhawk入门知识
    [转]错误记录
    华为上机试题:最高分是多少
    [转]opencv学习资料
    像素点的Hessian矩阵
    排序算法
  • 原文地址:https://www.cnblogs.com/lekko/p/2784789.html
Copyright © 2020-2023  润新知