【问题标题】:Dynamically setting DataGrid Columns to ComboBox Columns via data-binding通过数据绑定将 DataGrid Columns 动态设置为 ComboBox Columns
【发布时间】:2018-01-20 08:08:46
【问题描述】:

我有一个绑定到我称之为“GridCollection”的 DataTable 的 DataGrid:

<!--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>

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

我尝试通过添加绑定到 DataTable 列(“Caption”)属性的 DataTrigger 来实现此目的,然后相应地更新组合框的 Visibility。

我的理解是这种情况下的DataContext就是DataTable的Columns。

我已尝试设置 DataTable 列的“Caption”属性以匹配 DataTrigger(“ShowComboBox”)中指定的值:

ViewModel.GridCollection.Columns[index].Caption = "ShowComboBox";

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

我不确定是绑定有问题,还是其他问题。

感谢任何帮助!

【问题讨论】:

    标签: c# wpf xaml mvvm datagrid


    【解决方案1】:

    由于DataColumn 没有实现INotifyPropertyChanged 接口并向WPF 发出属性更改通知,因此这不起作用。

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

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

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

    【讨论】:

    • 谢谢。我假设 DataColumn 实现了 INotifyPropertyChanged,因为 DataGrid 的其余部分正在正确更新。似乎 DataTable 至少实现了它......我遇到的问题是从文件中读取列名,并且在运行时之前无法知道哪些需要是组合框列。有什么方法可以在不知道列名或索引的情况下在 XAML 中编写此绑定?
    • 为什么要绑定?它的哪一部分是动态的?您不能按照我在回答中的建议动态添加标题列吗?
    • 列标题是动态的(实际上,整个表都是从文件中读取的)。我的代码中的“标题”是单个 DataColumn 的属性,而不是 Column 的标题名称。我需要绑定到 DataColumn 的属性。这就是我所指的绑定。
    • 如前所述,您不能绑定到 DataColumn 的属性,但可以绑定到列本身。这些是动态的。所以我不太明白你的问题。
    • 我可以通过绑定到整个列来设置组合框的可见性吗?如果我不能使用属性,什么会触发可见性的变化?
    【解决方案2】:

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

    这里是适合我的代码:

    窗口的 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; }
        }
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-05-25
      • 2020-04-20
      • 1970-01-01
      • 2017-08-18
      • 2011-05-06
      • 2016-04-30
      • 1970-01-01
      • 2011-03-09
      • 2011-04-13
      相关资源
      最近更新 更多