通过数据绑定动态地将DataGrid列设置为ComboBox列

时间:2017-08-11 18:11:50

标签: c# wpf xaml mvvm datagrid

我有一个绑定到DataTable的DataGrid,我称之为" GridCollection" :

Gson

我希望能够动态更新DataGrid列单元格模板以显示组合框。

我尝试通过将DataTrigger绑定到DataTable列的属性(" Caption"),然后相应地更新组合框的可见性来实现此目的。

我的理解是,在这种情况下,DataContext是DataTable的列。

我试过设置"标题" DataTable列的属性与DataTrigger中指定的值相匹配(" ShowComboBox"):

<!--DataGrid-->
    <DataGrid Name="DataGrid" ItemsSource="{Binding GridCollection}" >
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <ComboBox ItemsSource="{Binding SelectionOptions}">
                                <ComboBox.Style>
                                    <Style TargetType="ComboBox">
                                        <Setter Property="Visibility" Value="Collapsed"/>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Caption, Mode=TwoWay}" Value="ShowComboBox">
                                                <Setter Property="Visibility" Value="Visible"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </ComboBox.Style>
                            </ComboBox>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

在确认正在执行此代码行并且正在更新Caption属性之后,仍然没有对DataGrid进行任何更改。没有列显示组合框。

我不确定绑定是否存在问题,或者是否是其他问题。

感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

由于DataColumn没有实现INotifyPropertyChanged界面并向WPF提出属性更改通知,因此无法正常工作。

但是,如果您向DataTable添加一列并绑定到此列,它将起作用:

ViewModel.GridCollection.Columns.Add(new DataColumn("Caption"));

不同之处在于DataRowView类实现了INotifyPropertyChanged接口。这是WPF能够侦听源属性的更改并动态更新视图所必需的。

答案 1 :(得分:0)

如果更改布局,则需要重置绑定。 从数据网格中删除绑定/数据源。更改标题值并将源再次绑定到数据网格。

这里的代码对我有用:

窗口的XAML

Window x:Class="WpfApplication7.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication7"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <DataGrid Name="grd" AutoGenerateColumns="False" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Path=DataContext}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="01" Binding="{Binding Name}" />
            <DataGridTextColumn Header="02" Binding="{Binding LastName}" />
            <DataGridTemplateColumn Header="CBX">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox>
                            <ComboBox.Style>
                                <Style TargetType="ComboBox">
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=Caption, Mode=TwoWay}" Value="ShowCombobox">
                                            <Setter Property="Visibility" Value="Collapsed" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </ComboBox.Style>
                        </ComboBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    <Button Content="Click" Click="Button_Click" Grid.Row="1"/>
</Grid>
</Window>

背后的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication7
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {

        items soureitems = new items();

        for(int i = 0; i <= 10; i++)
        {
            item sourceitem = new item();
            sourceitem.Name = "John";
            sourceitem.LastName = "Doe";
            sourceitem.Caption = "";
            soureitems.Add(sourceitem);
        }

        this.DataContext = soureitems;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {

        items sourceitems = (items)(this.DataContext);
        this.DataContext = null;
        foreach (item sourceitem in sourceitems)
        {
            if(sourceitem.Caption != "ShowCombobox")
            {
                sourceitem.Caption = "ShowCombobox";
            } else
            {
                sourceitem.Caption = "";
            }
        }
        this.DataContext = sourceitems;
    }
}

public class items : System.Collections.ObjectModel.ObservableCollection<item> { }

public class item
{
    string _Name;
    string _LastName;
    string _Caption;
    public string Name {
        get { return _Name; }
        set { _Name = value; }
    }
    public string LastName
    {
        get { return _LastName; }
        set { _LastName = value; }
    }
    public string Caption
    {
        get { return _Caption; }
        set { _Caption = value; }
    }
}
}