WPF:将按钮列添加到数据表中

4

如何在数据表格中通过编程方式添加按钮列?我想在代码后台文件中实现此功能。

同时,我希望根据记录选择性地启用或禁用此按钮(如果状态为“打开”,则启用它,否则禁用此按钮)。这里的状态是数据源中的一列。

谢谢, 阿比


http://stackoverflow.com/questions/1754337/how-to-add-button-dynamically-in-datagrid-in-wpf - Peter
尝试这个:https://dev59.com/qHI-5IYBdhLWcg3woJ9J#1755556 - viky
3个回答

6

viky提供的答案总结了从源代码中添加按钮列的想法。我编写了一个简短的示例,还展示了你的第二个问题,即如何基于网格中的数据启用/禁用按钮。我在4.0中使用了DataGrid,但3.5的工具包也应该可以。

首先,我从XAML中添加了一个Name列。这不是必需的,但只是表明您可以将XAML和C#添加组合到网格中。请注意,我在此处为网格命名,以便我有一种方法引用它在C#局部类中。

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Data Grid Populated in XAML and C#">
    <Grid>
        <DataGrid x:Name="_gridControl" IsReadOnly="True" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Width="*" Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

现在,在代码后面我做了两件事。除了添加按钮列和数据元素(它们具有名称和状态),我创建了一个转换器类,如果值为“Open”,则返回true,否则返回false。然后,在设置绑定时(与值不同),我还添加了我的转换器,这样当ItemsControl为我的项生成和绑定容器时,显示的按钮的IsEnabled状态将链接到我的项目的Status字段。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var buttonTemplate = new FrameworkElementFactory(typeof(Button));
        buttonTemplate.SetBinding(Button.ContentProperty, new Binding("Name"));
        buttonTemplate.SetBinding(Button.IsEnabledProperty, new Binding("Status")
        {
            Converter = new StatusToEnabledConverter()
        });
        buttonTemplate.AddHandler(
            Button.ClickEvent, 
            new RoutedEventHandler((o, e) => MessageBox.Show("hi"))
        );
        this._gridControl.Columns.Add(
            new DataGridTemplateColumn()
            {
                Header = "Close Button",
                CellTemplate = new DataTemplate() { VisualTree = buttonTemplate }
            }
        );

        this._gridControl.ItemsSource = new object[]
        {
            new { Name = "First Item", Status = "Open" },
            new { Name = "Second Item", Status = "Open" },
            new { Name = "Third Item", Status = "Closed" },
            new { Name = "Fourth Item", Status = "Closed" },
            new { Name = "Fifth Item", Status = "Open" }
        };
    }
}

public class StatusToEnabledConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        return "Open".Equals(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        throw new System.NotImplementedException();
    }
}

最后需要注意的一点是,我只在调用InitializeComponent后才从C#修改DataGrid。对于一个包含XAML和C#部分的WPF内容控件,这一点非常重要,因为通过XAML完成的对象构建需要在开始修改XAML中定义的对象之前完成。

希望这能帮到你!


不错的例子。然而,它过度使用了var关键字。没有理由为ButtonTemplate使用隐式类型。它可以简单地是:FrameworkElementFactory buttonTemplate = new FrameworkElementFactory(typeof(Button)); - xr280xr
6
这多出来的20个字符给我带来了什么好处? - timmyl
我想既然编译器仍将变量视为强类型,那只是个人癖好。抱歉,我收回了。 - xr280xr

2

Xaml :

<DataGridTemplateColumn>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Button Click="Details">Details</Button>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>

代码后置

       private IEnumerable<DataGridRow> GetDataGridRowsForButtons(DataGrid grid)
    { //IQueryable 
        var itemsSource = grid.ItemsSource as IEnumerable;
        if (null == itemsSource) yield return null;
        foreach (var item in itemsSource)
        {
            var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
            if (null != row & row.IsSelected) yield return row;
        }
    }

    void Details(object sender, RoutedEventArgs e)
    {

        for (var vis = sender as Visual; vis != null; vis = VisualTreeHelper.GetParent(vis) as Visual)
            if (vis is DataGridRow)
            {
               // var row = (DataGrid)vis;

                var rows = GetDataGridRowsForButtons(dgv_Students);
                string id;
                foreach (DataGridRow dr in rows)
                {
                    id = (dr.Item as tbl_student).Identification_code;
                    MessageBox.Show(id);
                }
                break;
            }
    }

点击按钮后,该行的ID将返回给您,并且您可以将其用作按钮名称。


0

XAML:

  <DataGrid.Columns>
                <DataGridTemplateColumn Header="Check">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox  x:Name="chkName" IsChecked="{Binding IsChecked ,  UpdateSourceTrigger=PropertyChanged}" Click="chkName_Click">
                            </CheckBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                
                <DataGridTemplateColumn Header="as">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Click="OnAddQuantityClicked">hello</Button>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>

代码后台:

private async void OnAddQuantityClicked(object sender, RoutedEventArgs e)
        {
            if (sender is Button)
            {
                var temps = (Models.TempV)mainDatagrid.SelectedItem;
                //Button button = (Button)e.OriginalSource;
                if (temps.IsChecked is true)
                {
                    MessageBox.Show("Do something when it is True");
                }
                else
                {
                    MessageBox.Show("Do something when it is False");
                }
            }
        }

很遗憾,对于将一个十多年前的问题重新提出并解决,我们无法颁发“金铲子”奖励。不过,面对这些“僵尸问题”,获得银牌可能会更有价值。鉴于该问题缺少动词:你是如何填补那个空缺的? - greybeard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接