向datagridView中的某些单元格添加按钮

问题描述 投票:0回答:1

C# WinForms 上有没有办法仅在某些单元格中添加按钮,以便它们(按钮)成为单元格的一部分?并添加该按钮的处理程序。 这需要将特定单元格的值插入到另一种形式中。但它不必执行表中的所有单元格。 就像图片上一样。


(来源:snag.gy

c# winforms button datagridview custom-cell
1个回答
2
投票

将此作为答案发布,因为 OP 要求这样做:

这是我的 WPF 对此的看法:

<Window x:Class="MiscSamples.DataGridCustomCells"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MiscSamples"
        Title="DataGridCustomCells" Height="300" Width="300">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisibiltyConverter"/>
        <Style TargetType="DataGridCell" x:Key="ButtonCell">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <!-- ControlTemplate obtained with Expression Blend -->
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                                Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                            <Grid>
                                <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                <Button Height="16" Width="16" VerticalAlignment="Top" HorizontalAlignment="Right"
                                        Visibility="{Binding (local:DataGridParameters.ShowButton), 
                                                             RelativeSource={RelativeSource TemplatedParent},
                                                             Converter={StaticResource BoolToVisibiltyConverter}}"
                                        Command="{Binding CellButtonCommand, RelativeSource={RelativeSource AncestorType=Window}}"
                                        CommandParameter="{Binding (local:DataGridParameters.ButtonValue), RelativeSource={RelativeSource TemplatedParent}}"/>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>


    <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding LastName}">
                <DataGridTextColumn.CellStyle>
                    <Style TargetType="DataGridCell" BasedOn="{StaticResource ButtonCell}">
                        <Setter Property="local:DataGridParameters.ShowButton" Value="{Binding DataContext.ShowButtonOnLastName, RelativeSource={RelativeSource Self}}"/>
                        <Setter Property="local:DataGridParameters.ButtonValue" Value="{Binding DataContext.LastName, RelativeSource={RelativeSource Self}}"/>
                    </Style>
                </DataGridTextColumn.CellStyle>    
            </DataGridTextColumn>

            <DataGridTextColumn Binding="{Binding FirstName}">
                <DataGridTextColumn.CellStyle>
                    <Style TargetType="DataGridCell" BasedOn="{StaticResource ButtonCell}">
                        <Setter Property="local:DataGridParameters.ShowButton" Value="{Binding DataContext.ShowButtonOnFirstName, RelativeSource={RelativeSource Self}}"/>
                        <Setter Property="local:DataGridParameters.ButtonValue" Value="{Binding DataContext.FirstName, RelativeSource={RelativeSource Self}}"/>
                    </Style>
                </DataGridTextColumn.CellStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

背后代码:

public partial class DataGridCustomCells : Window
    {
        public ICommand CellButtonCommand { get; set; }

        public DataGridCustomCells()
        {
            CellButtonCommand = new Command<object>(OnCellCommandExecuted){IsEnabled = true};

            InitializeComponent();

            DataContext = new List<DataGridSampleData>
                {
                    new DataGridSampleData() {LastName = "Simpson", FirstName = "Homer", ShowButtonOnFirstName = true},
                    new DataGridSampleData() {LastName = "Szyslak", FirstName = "Moe", ShowButtonOnLastName = true},
                    new DataGridSampleData() {LastName = "Gumble", FirstName = "Barney", ShowButtonOnFirstName = true},
                    new DataGridSampleData() {LastName = "Burns", FirstName = "Montgomery", ShowButtonOnLastName = true},
                };
        }

        private void OnCellCommandExecuted(object parameter)
        {
            MessageBox.Show("Command Executed: " + parameter);
        }
    }

示例数据类:

public class DataGridSampleData //TODO: Implement INotifyPropertyChanged
{
    public string LastName { get; set; }

    public string FirstName { get; set; }

    public bool ShowButtonOnFirstName { get; set; }

    public bool ShowButtonOnLastName { get; set; }
}

辅助类:

public static class DataGridParameters
{
    public static readonly DependencyProperty ShowButtonProperty = DependencyProperty.RegisterAttached("ShowButton", typeof(bool), typeof(DataGridParameters));

    public static void SetShowButton(DependencyObject obj, bool value)
    {
        obj.SetValue(ShowButtonProperty, value);
    }

    public static bool GetShowButton(DependencyObject obj)
    {
        return (bool) obj.GetValue(ShowButtonProperty);
    }

    public static readonly DependencyProperty ButtonValueProperty = DependencyProperty.RegisterAttached("ButtonValue", typeof(object), typeof(DataGridParameters));

    public static void SetButtonValue(DependencyObject obj, object value)
    {
        obj.SetValue(ButtonValueProperty, value);
    }

    public static object GetButtonValue(DependencyObject obj)
    {
        return obj.GetValue(ButtonValueProperty);
    }
}

通用基本委托命令:

    //Dead-simple implementation of ICommand
    //Serves as an abstraction of Actions performed by the user via interaction with the UI (for instance, Button Click)
    public class Command<T>: ICommand
    {
        public Action<T> Action { get; set; }

        public void Execute(object parameter)
        {
            if (Action != null && parameter is T)
                Action((T)parameter);
        }

        public bool CanExecute(object parameter)
        {
            return IsEnabled;
        }

        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                if (CanExecuteChanged != null)
                    CanExecuteChanged(this, EventArgs.Empty);
            }
        }

        public event EventHandler CanExecuteChanged;

        public Command(Action<T> action)
        {
            Action = action;
        }
    }

结果:

enter image description here

  • 请注意,我正在使用 附加属性 来启用现有
    DataGridCell
    中的额外行为。
  • 此外,我使用 DelegateCommand 将这些按钮全部重定向到相同的底层逻辑。
  • 我的示例中没有一行代码处理任何 UI 元素。一切都是通过数据绑定完成的。这就是在 WPF 中编码的方式。
  • 这是一个非常基本且初级的示例。您可以通过定义
    RowViewModel<TEntity>
    来创建更具可扩展性的解决方案,其中每个单元格值都包含在
    CellViewModel<TValue>
    中,定义按钮功能以及是否显示按钮等。
  • 没有“所有者抽奖”,没有 P/Invoke,没有可怕的代码隐藏黑客。
  • WPF 很棒。只需将我的代码复制到
    File -> New Project -> WPF Application
    中即可亲自查看结果。
© www.soinside.com 2019 - 2024. All rights reserved.