欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WPF DataGrid ComboBox 下拉框数据绑定。且默认显示下拉框,可与其他列绑定联动。

程序员文章站 2022-06-07 18:05:30
...

这段时间在折腾 WPF 的表格控件。为了实现表格里带下拉框,同时联动另一列,真是想的快吐了。
完整版代码放在文末,先展示最终方案:

WPF DataGrid ComboBox 下拉框数据绑定。且默认显示下拉框,可与其他列绑定联动。

WPF DataGrid ComboBox 下拉框数据绑定。且默认显示下拉框,可与其他列绑定联动。

WPF DataGrid ComboBox 下拉框数据绑定。且默认显示下拉框,可与其他列绑定联动。

方案也是改了又改, 从直接的 DataGridComboBoxColumn 到 DataGridTemplateColumn的 CellEditingTemplate 再到这个完成版 DataGridTemplateColumn的CellTemplate 加事件。

第一版:

能显示,可惜不能保存修改,不能联动其他列。

<DataGridComboBoxColumn Header="单位" SelectedItemBinding="{Binding UnitStr}" ItemsSource="{Binding UnitList}"/>

第二版:
能显示,能保存,能联动其他列,就是不能默认显示为下拉框。必须点击后,才会出现下拉框。而且保存必须按回车键...

<DataGridTemplateColumn Header="单位EU" Width="2*">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="3*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Text="{Binding UnitStr, Mode=OneWay}" />
                <Image Grid.Column="1" Width="5" Height="5" Source="/SensorMonitoring;component/UserRes/DownArrow.png" />
            </Grid>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox Tag="{Binding idx}" IsEditable="{Binding isUnitFreeInput}" Text="{Binding UnitStr}" ItemsSource="{Binding unitList}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
public string UnitStr
{
	get
	{
		return this.unitstr;
	}
	set
	{
		this.unitstr = value;
                  //联动其他列
		if (this.sType.Contains("压力"))
		{
			this.TCoef_K = CurrencyAgreement.PUnits.GetRatioNum(this.unitstr);
			this.TCoef_B = 0f;
		}
		this.PropertiesC();
	}
}	

第三版 也是最终版    :
能显示,能保存,能联动其他列,而且默认显示为下拉框。
要点有两个
1 DataGridTemplateColumn 加 CellTemplate的ComboBox。保证了能直接显示下拉框。
2 CellTemplate.ComboBox 的SelectionChanged 事件。 只有CellTemplate 的SelectionChanged事件才会触发。也由此 可以在这个事件中手动保存 列值UnitStr 。以及联动其他列。

<DataGrid Name="dataGrid0" ItemsSource="{Binding}" AutoGenerateColumns="False" SelectionMode="Single"
    SelectionUnit="Cell" CanUserSortColumns="False" CanUserReorderColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="变换系数K" Width="2*" Binding="{Binding CoefK}" />
        <DataGridTemplateColumn Header="单位EU" Width="2*" >
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ComboBox x:Name="cellComboBox0" Tag="{Binding Idx}"  SelectedItem="{Binding UnitStr}" ItemsSource="{Binding UnitList}" SelectionChanged="ComboBox_SelectionChanged"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
	var cb = (sender as ComboBox);
	if (cb == null || cb.Tag == null) return;
	int idx = int.Parse(cb.Tag.ToString());
   // var bindDataGridDatas = this.dataGrid0.ItemsSource as BindDataGridData[];//成员变量和这里转换都可以。
	bindDataGridDatas[idx].UnitStr = (string)cb.SelectedItem;//手动保存到数据结构
	bindDataGridDatas[idx].UpdateKBValue(); //联动CoefK值
}
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfApp2.DataGrid
{
    class BindDataGridData : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private void PropertiesC([CallerMemberName] string propertyName = "")
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public int Idx { get; set; } = 0;

        string unitstr = "Pa";

        public string UnitStr
        {
            get
            {
                return this.unitstr;
            }
            set
            {
                this.unitstr = value;
                this.PropertiesC();
            }
        }

        public string[] UnitList { get; set; } = new string[] { "Pa", "kPa", "MPa" };

        public static readonly float[][] KBList = new float[][] { new float[] { 1, 1 }, new float[] { 1000, 2 }, new float[] { 1000000, 3 } };

        float coefK { get; set; } = 1f;

        public float CoefK
        {
            get
            {
                return this.coefK;
            }
            set
            {
                this.coefK = value;
                this.PropertiesC();
            }
        }

        public void UpdateKBValue()
        {
            int idx = -1;
            for (int j = 0; j < this.UnitList.Length; j++)
            {
                if (this.UnitList[j] == this.unitstr)
                {
                    idx = j; break;
                }
            }
            if (idx == -1) return;
            //throw new System.Exception("no Unit in UnitList:  unit " + this.UnitStr + " UnitList {" + string.Join(", ", this.UnitList)+"}");

            this.CoefK = BindDataGridData.KBList[idx][0];
        }
    }
}

参考:

多个忘了来源的博客。感谢之。