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

时间:2013-05-26 17:58:05

标签: c# winforms button datagridview custom-cell

C#WinForms上是否有任何方法只在某些单元格中添加按钮,以便它们(按钮)成为单元格的一部分?并为此按钮添加处理程序。 这需要以特定单元格的值插入另一种形式。但它不必完成表中的所有单元格。 就像图片一样。

already added buttons http://i.snag.gy/vpD9Q.jpg

1 个答案:

答案 0 :(得分: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);
    }
}

通用基本DelegateCommand:

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

  • 请注意,我正在使用Attached Properties在现有DataGridCell中启用额外行为。
  • 另外,我正在使用DelegateCommand将这些按钮全部重定向到相同的基础逻辑。
  • 我的示例中没有一行代码可以处理任何UI元素。一切都是通过DataBinding完成的。这就是你在WPF中编码的方式。
  • 这是一个非常基本和基本的例子。您可以通过定义RowViewModel<TEntity>来创建更具可扩展性的解决方案,其中每个单元格值都包含在CellViewModel<TValue>中,用于定义按钮功能以及是否显示按钮等等。
  • 没有“所有者抽奖”,没有P / Invoke,没有可怕的代码隐藏黑客。
  • WPF Rocks。只需在File -> New Project -> WPF Application中复制我的代码,然后自行查看结果。