使用datagridtemplatecolumn中的复选框会发出WPF

时间:2011-06-04 14:27:25

标签: wpf datagrid checkbox

我正在使用类似的技术 http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/df77a277-91d4-41f1-a42a-0fa02a443ff4/ 我在代码中构建了DaataGridTemplateColumn,我正在尝试解决WPF中数据网格的“选择行,然后单击”复选框问题。

在一般意义上,这是有效的,但是如果我想在单击复选框时触发事件(即CellEditEnding或RowEditEnding),似乎我不能(根据http://social.msdn.microsoft.com/Forums/en/wpf/thread/bf080945-0092-43f5-b0eb-42b2edf53dc7

必须有办法解决这个问题。我想在我的模板列上使用某种路由事件,试图在单击复选框时触发数据网格事件,但这可能会变得很难看。最终,我需要能够有一个单击复选框,并能够触发数据网格事件。

请帮忙!

编辑:如果我可以让RowEditEnding开火(不知何故:通过。冒泡或其他什么)那么这不会是一个问题......我根本无法解决它......

有人???

谢谢

2 个答案:

答案 0 :(得分:1)

我遇到了你的问题并遇到了同样的问题。这是我的情况和解决方案,我认为它应该适用于你(和其他人)。我有一个允许输入新项目的数据网格,因此可能的值从0到无穷大。用户应该能够单击该复选框,只需单击一下按钮即可选中或取消选中。此外,还有其他字段也可以更新。我必须创建一个自定义数据网格控件来自动聚焦并开始编辑复选框:

public class CheckboxDataGrid : DataGrid {
        public CheckboxDataGrid() {
            EventManager.RegisterClassHandler(typeof(DataGridCell),
                DataGridCell.PreviewMouseLeftButtonDownEvent,
                new RoutedEventHandler(this.OnPreviewMouseLeftButtonDown));
        }


        private void OnPreviewMouseLeftButtonDown(object sender, RoutedEventArgs e) {
            DataGridCell cell = sender as DataGridCell;
            if (cell != null && !cell.IsEditing && !cell.IsReadOnly) {

                var parentRow = cell.Parent as DataGridRow;
                if (parentRow != null) {
                    SelectedIndex = parentRow.GetIndex();
                }
                CurrentCell = new DataGridCellInfo(cell);

                DependencyObject obj = FindVisualChild<CheckBox>(cell);
                if (obj != null) {
                    BeginEdit(e);
                    System.Windows.Controls.CheckBox cb = (System.Windows.Controls.CheckBox)obj;
                    cb.Focus();
                }
            }
        }
        public static TChild FindVisualChild<TChild>(DependencyObject obj) where TChild : DependencyObject {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is TChild) {
                    return (TChild)child;
                } else {
                    TChild childOfChild = FindVisualChild<TChild>(child);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
        }
    }

由于WPF处理数据网格中新项目的方式,我还需要一个转换器来忽略新的项目绑定消息:

public class IgnoreNewItemPlaceHolderConverter : IValueConverter {
        private const string NewItemPlaceholderName = "{NewItemPlaceholder}";

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
            if (value != null && value.ToString() == NewItemPlaceholderName)
                return DependencyProperty.UnsetValue;
            return value;
        }

    }

以下是datagrid的相关XAML:

<chkDatagrid:CheckboxDataGrid AutoGenerateColumns="False" 
                        ItemsSource="{Binding ElementName=dgPurchaseOrders, Path=SelectedItem.Releases, NotifyOnSourceUpdated=True}" AlternatingRowBackground="#1E000000" 
                      DockPanel.Dock="Bottom" HorizontalAlignment="Left" SelectedItem="{Binding SelectedRelease, Mode=TwoWay, Converter={StaticResource ignoreNewItemPlaceHolderConverter}}"
                      MinHeight="100">
<b:Interaction.Triggers>
                            <b:EventTrigger EventName="RowEditEnding">
                                <b:InvokeCommandAction  Command="{Binding ReleaseRowEditEndingCommand}" CommandParameter="{Binding SelectedRelease}"/>
                            </b:EventTrigger>
                        </b:Interaction.Triggers>
                        <DataGrid.Columns>
                            <DataGridCheckBoxColumn Header="Is Paid" Binding="{Binding IsPaid, UpdateSourceTrigger=PropertyChanged}" />

                            <DataGridTextColumn Header="Amount" Binding="{Binding Amount,  UpdateSourceTrigger=PropertyChanged}" />
                            <DataGridTextColumn Header="Description" Binding="{Binding Description, UpdateSourceTrigger=PropertyChanged}" />
                            <DataGridTextColumn Header="Invoice Number" Binding="{Binding InvoiceNumber, UpdateSourceTrigger=PropertyChanged}" />
                            <DataGridTextColumn Header="Invoice Receive Date" Binding="{Binding InvoiceRecvDate, UpdateSourceTrigger=PropertyChanged}" />
                        </DataGrid.Columns>
                    </chkDatagrid:CheckboxDataGrid>

你会在这里注意一些事情。我正在订阅RowEditEnding事件,用于编辑和提交列以及将转换器应用到新行。

最后,这是更新附加实体的代码:

private void OnReleaseRowEditEnding(object arg) {
            if (arg != null) {
                EMService.EMEntities etx = GetEMEntities();
                EMService.Release release = (EMService.Release)arg;
                if (release.ReleaseID == 0) {
                    release.EncumbranceID = SelectedPurchaseOrder.EncumbranceID;
                    release.CreatedOn = DateTime.Now;
                    release.CreatedBy = CurrentUser.Username;
                    release.ModifiedOn = DateTime.Now;
                    release.ModifiedBy = CurrentUser.Username;
                    etx.AddObject("Releases", release);
                } else {
                    EMService.Release existingRelease = etx.Releases.Where(e => e.ReleaseID == release.ReleaseID).First();
                    existingRelease.Amount = release.Amount;
                    existingRelease.Description = release.Description;
                    existingRelease.InvoiceNumber = release.InvoiceNumber;
                    existingRelease.InvoiceRecvDate = release.InvoiceRecvDate;
                    existingRelease.IsPaid = release.IsPaid;
                    release.ModifiedOn = DateTime.Now;
                    release.ModifiedBy = CurrentUser.Username;
                    etx.UpdateObject(existingRelease);
                }
                etx.SaveChanges();
            }
        }

消化很多,但从长远来看它最终会起作用。谁知道WPF数据网格会如此懒散。

答案 1 :(得分:0)

这里的答案是不处理RowEditEnding中的任何复选框(或尝试)。相反,使用PropertyChange事件侦听您绑定的复选框,并相应地执行操作(即在设置复选框的绑定时保存更改)