DataGridComboBoxColumn绑定后显示空白的问题

12 篇文章 0 订阅

DataGridComboBoxColumn绑定后显示空白的问题

在设计一个带有DataGridComboBoxColumn的用户控件时,发现绑定之后的DataGridComboBoxColumn居然是空白的,有问题的设计器代码如下。

<UserControl x:Class="SouthGIS.ToolKit.UCMDBPath"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" Height="298.4" Width="468">
    <Grid Margin="0,0,0,0" Height="298" VerticalAlignment="Top">
        <Button x:Name="btn_select" Content="选择mdb文件路径" Margin="325,264,0,0"  HorizontalAlignment="Left" Width="133" Height="24" VerticalAlignment="Top" Click="btn_select_Click"/>

        <DataGrid Name="dg_table" HorizontalAlignment="Left" Width="448" Margin="10,10,0,-2" Height="249" VerticalAlignment="Top" IsSynchronizedWithCurrentItem="False" AutoGenerateColumns="False" AutomationProperties.IsRowHeader="True" AutomationProperties.IsColumnHeader="True" RowHeaderWidth="40" SelectionChanged="dg_table_SelectionChanged" Background="#FFFDFDFD" CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="dgc_mdbname" IsReadOnly="True" Binding="{Binding Path=get_path}" ClipboardContentBinding="{x:Null}" Foreground="Black" Header="数据库名称" CanUserSort="False" CanUserResize="False"/>
                <DataGridTextColumn x:Name="dgc_code" Binding="{Binding Path=get_xzqcode}" ClipboardContentBinding="{x:Null}" Header="行政代码占位"/>
                <DataGridTextColumn x:Name="dgc_xzq" Binding="{Binding Path=get_xzq}" ClipboardContentBinding="{x:Null}" Header="行政区占位" Foreground="Black"/>
                <DataGridComboBoxColumn x:Name="dgc_splitedtable" ItemsSource="{Binding Path=get_tablenames}"  ClipboardContentBinding="{x:Null}" Header="拆分对象表" SelectedValueBinding="{x:Null}" SelectedItemBinding="{x:Null}" TextBinding="{x:Null}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

后台cs代码中,DataGrid绑定的ItemSource为以下结构,在一个函数中绑定。

public class MDBStruct : INotifyPropertyChanged
    {

        private string m_path;
        private ObservableCollection<string> m_tablenames;
        private string m_xzq;
        private string m_xzqcode;
        private string m_selectedname;

        public MDBStruct()
        {

        }

        public MDBStruct(string path, string xzqcode, string xzq, ObservableCollection<string> tablenames)
        {
            try
            {
                this.m_path = path;
                this.m_xzqcode = xzqcode;
                this.m_xzq = xzq;
                this.m_tablenames = tablenames;
                this.m_selectedname = tablenames[0];
            }
            catch (Exception ex)
            {
                this.m_path = "";
                this.m_xzqcode = "";
                this.m_xzq = "";
                this.m_tablenames = new ObservableCollection<string>();
                this.m_selectedname = "";
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public string get_path
        {
            get { return m_path; }
            set
            {
                m_path = value;
                if (PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("get_path"));
                }
            }
        }
        public string get_selectedname
        {
            get { return m_selectedname; }
            set
            {
                m_selectedname = value;
                if (PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("get_selectedname"));
                }
            }
        }
        public string get_xzq
        {
            get { return m_xzq; }
            set
            {
                m_xzq = value;
                if (PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("get_xzq"));
                }
            }
        }
        public string get_xzqcode
        {
            get { return m_xzqcode; }
            set
            {
                m_xzqcode = value;
                if (PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("get_xzqcode"));
                }
            }
        }
        public ObservableCollection<string> get_tablenames
        {
            get { return m_tablenames; }
            set
            {
                m_tablenames = value;
                if (PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("get_tablenames"));
                }
            }
        }
    }



**/////////绑定函数/////////**

private void bindingfunc()
{
    dg_table.ItemsSource = MDBStructs;
}

绑定运行后的效果截图如下:
选项为空

我在这里困了很久,一开始以为是ObservableCollection< string>类的问题,在这上面折腾很久。最后查资料,说是DataGridColumn对数据源是有要求的:

使用下列选项之一,若要填充下拉列表,首先设置 ComboBox 的 ItemsSource 属性:
1、静态资源。有关更多信息,请参见 StaticResource 标记扩展。
2、x: 静态代码实体。有关更多信息,请参见 x:Static 标记扩展。
3、ComboBoxItem 类型的内联集合。

怎么说,就是DataGridColumn的ItemSource绑定的对象List必须是静态(static),已经确定的,并不能在代码中根据数据库读取结果生成,即必须是一开始已经构造的类,如:

List< string> L1 = new List< string>();
L1.Add("123");
L1.Add("456");
L1.Add("1234");

上面这种已经确定好的,不会变动的组类。

但是我的需求是每一行的combobox内的itemsource都是不同的,而且有很多行,即,我的MDBStruct就是一个数组类型。这样可以用到下面的两个方法。

方法一:折中法

使用DataGridTemplateColumn,代码和效果如下:
(只贴关键部分)

<DataGridTemplateColumn  x:Name="dgc_splitedtable" Header="拆分对象表">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ComboBox SelectedValue="{Binding Path=get_selectedname}" ItemsSource="{Binding Path=get_tablenames}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>               
</DataGridTemplateColumn>

DataGridTemplateColumn

可以看见基本实现效果,但是不能实现双向同步,只能实现展示。原因大致如下:

基本上原因是这样的:DataGrid的列并没有数据上下文,所以DataGridTemplateColumn中的ComoBox从未添加到“Visual Tree(可视化树)”中。只要Grid绘制了单元,并且得到了数据上下文后,就能正常地使用ItemsSource属性来完成绑定了。

这样可以用第二种方法,使用DataGridComboboxColumn来解决

方法二:修改法

修改DataGridComboboxColumn的代码,修改成如下
(只贴关键部分)

<DataGridComboBoxColumn Header="拆分对象表(修正)">
    <DataGridComboBoxColumn.EditingElementStyle>
         <Style TargetType="ComboBox">
            <Setter Property="SelectedValue" Value="{Binding Path=get_selectedname}" />
            <Setter Property="ItemsSource" Value="{Binding Path=get_tablenames}" />
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="SelectedValue" Value="{Binding Path=get_selectedname}" />
            <Setter Property="ItemsSource" Value="{Binding Path=get_tablenames}" />
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
</DataGridComboBoxColumn>

为什么要贴EditingElementStyle和ElementStyle两个部分呢?
因为当你只贴EditingElementStyle时,虽然combobox有选项,带是selectedvalue是无法显示的,你也无法选择中某个东西。
而当你只有ElementStyle时,你将和原来没修改之前的一样,没有选项,只有已选择的项。因此要两个一起写。在这里就不贴有问题的截图了,直接贴最终成果。
DataGridComboboxColumn
这样,实现了我最初的需求。
感谢原技术博客博主:上衫越野,此处链接到本文参考的博客。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

话与山鬼听

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值