Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在WPF DataGrid中单击编辑_C#_.net_Wpf_Events_Xaml - Fatal编程技术网

C# 在WPF DataGrid中单击编辑

C# 在WPF DataGrid中单击编辑,c#,.net,wpf,events,xaml,C#,.net,Wpf,Events,Xaml,我希望用户能够将单元格置于编辑模式,并通过单击突出显示单元格所在的行。默认情况下,这是双击 如何覆盖或实现此功能?来自: XAML: <!-- SINGLE CLICK EDITING --> <Style TargetType="{x:Type dg:DataGridCell}"> <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftBu

我希望用户能够将单元格置于编辑模式,并通过单击突出显示单元格所在的行。默认情况下,这是双击

如何覆盖或实现此功能?

来自:

XAML:

<!-- SINGLE CLICK EDITING -->
<Style TargetType="{x:Type dg:DataGridCell}">
    <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown"></EventSetter>
</Style>
//
// SINGLE CLICK EDITING
//
private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DataGridCell cell = sender as DataGridCell;
    if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
    {
        if (!cell.IsFocused)
        {
            cell.Focus();
        }
        DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
        if (dataGrid != null)
        {
            if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
            {
                if (!cell.IsSelected)
                    cell.IsSelected = true;
            }
            else
            {
                DataGridRow row = FindVisualParent<DataGridRow>(cell);
                if (row != null && !row.IsSelected)
                {
                    row.IsSelected = true;
                }
            }
        }
    }
}

static T FindVisualParent<T>(UIElement element) where T : UIElement
{
    UIElement parent = element;
    while (parent != null)
    {
        T correctlyTyped = parent as T;
        if (correctlyTyped != null)
        {
            return correctlyTyped;
        }

        parent = VisualTreeHelper.GetParent(parent) as UIElement;
    }

    return null;
}

代码隐藏:

<!-- SINGLE CLICK EDITING -->
<Style TargetType="{x:Type dg:DataGridCell}">
    <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown"></EventSetter>
</Style>
//
// SINGLE CLICK EDITING
//
private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DataGridCell cell = sender as DataGridCell;
    if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
    {
        if (!cell.IsFocused)
        {
            cell.Focus();
        }
        DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
        if (dataGrid != null)
        {
            if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
            {
                if (!cell.IsSelected)
                    cell.IsSelected = true;
            }
            else
            {
                DataGridRow row = FindVisualParent<DataGridRow>(cell);
                if (row != null && !row.IsSelected)
                {
                    row.IsSelected = true;
                }
            }
        }
    }
}

static T FindVisualParent<T>(UIElement element) where T : UIElement
{
    UIElement parent = element;
    while (parent != null)
    {
        T correctlyTyped = parent as T;
        if (correctlyTyped != null)
        {
            return correctlyTyped;
        }

        parent = VisualTreeHelper.GetParent(parent) as UIElement;
    }

    return null;
}
//
//单击编辑
//
私有void DataGridCell_PreviewMouseLeftButtonDown(对象发送器,鼠标按钮ventargs e)
{
DataGridCell=发送方为DataGridCell;
if(cell!=null&&!cell.IsEditing&&!cell.IsReadOnly)
{
如果(!cell.IsFocused)
{
cell.Focus();
}
DataGrid DataGrid=FindVisualParent(单元格);
if(dataGrid!=null)
{
if(dataGrid.SelectionUnit!=DataGridSelectionUnit.FullRow)
{
如果(!cell.IsSelected)
cell.IsSelected=true;
}
其他的
{
DataGridRow行=FindVisualParent(单元格);
if(row!=null&&!row.IsSelected)
{
row.IsSelected=true;
}
}
}
}
}
静态T FindVisualParent(UIElement元素),其中T:UIElement
{
UIElement父元素=元素;
while(父级!=null)
{
T correctlyTyped=父项为T;
if(correctlyTyped!=null)
{
返回正确类型;
}
parent=VisualTreeHelper.GetParent(parent)作为UIElement;
}
返回null;
}

以下是我如何解决此问题的:

<DataGrid DataGridCell.Selected="DataGridCell_Selected" 
          ItemsSource="{Binding Source={StaticResource itemView}}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Nom" Binding="{Binding Path=Name}"/>
        <DataGridTextColumn Header="Age" Binding="{Binding Path=Age}"/>
    </DataGrid.Columns>
</DataGrid>
来自的解决方案对我来说非常有效,但我使用ResourceDictionary中定义的样式为每个DataGrid启用了它。要在资源字典中使用处理程序,需要向其中添加代码隐藏文件。以下是您的操作方法:

这是DataGridStyles.xaml资源字典:


注意根元素中的x:Class属性。 创建一个类文件。在本例中,它将是DataGridStyles.xaml.cs。将此代码放入:

using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;

namespace YourNamespace
{
    partial class DataGridStyles : ResourceDictionary
    {

        public DataGridStyles()
        {
          InitializeComponent();
        }

     // The code from the myermian's answer goes here.
}

Michael Bergeron的回答对我来说是一个很好的开始,我找到了一个适合我的解决方案。为了允许对已经处于编辑模式的同一行中的单元格进行单击编辑,我必须对其进行一些调整。使用SelectionUnit Cell对我来说是没有选择的

我使用DataGridCell.GotFocus事件,而不是使用DataGridCell.Selected事件,该事件仅在第一次单击行的单元格时触发

<DataGrid DataGridCell.GotFocus="DataGrid_CellGotFocus" />

如果您这样做,您将始终保持正确的单元格聚焦并处于编辑模式,但单元格中的任何控件都不会聚焦,我这样解决了这个问题

private void DataGrid_CellGotFocus(object sender, RoutedEventArgs e)
{
    // Lookup for the source to be DataGridCell
    if (e.OriginalSource.GetType() == typeof(DataGridCell))
    {
        // Starts the Edit on the row;
        DataGrid grd = (DataGrid)sender;
        grd.BeginEdit(e);

        Control control = GetFirstChildByType<Control>(e.OriginalSource as DataGridCell);
        if (control != null)
        {
            control.Focus();
        }
    }
}

private T GetFirstChildByType<T>(DependencyObject prop) where T : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(prop); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild((prop), i) as DependencyObject;
        if (child == null)
            continue;

        T castedProp = child as T;
        if (castedProp != null)
            return castedProp;

        castedProp = GetFirstChildByType<T>(child);

        if (castedProp != null)
            return castedProp;
    }
    return null;
}
private void DataGrid\u CellGotFocus(对象发送方,RoutedEventArgs e)
{
//查找要成为DataGridCell的源
if(e.OriginalSource.GetType()==typeof(DataGridCell))
{
//开始对行进行编辑;
DataGrid grd=(DataGrid)发送方;
grd.BeginEdit(e);
Control=GetFirstChildByType(例如,原始源为DataGridCell);
if(控件!=null)
{
control.Focus();
}
}
}
私有T GetFirstChildByType(DependencyObject属性),其中T:DependencyObject
{
for(int i=0;i
用户2134678的答案有两个问题。一种是非常轻微的,没有功能性影响。另一个是相当重要的

第一个问题是,实际上是针对DataGrid而不是DataGridCell调用GotFocus。XAML中的DataGridCell限定符是冗余的

我发现答案的主要问题是Enter键行为被破坏。在正常的DataGrid行为中,Enter会将您移动到当前单元格下方的下一个单元格。然而,在幕后实际发生的是,GotFocus事件将被调用两次。一旦当前单元格失去焦点,新单元格获得焦点。但只要对第一个单元格调用BeginEdit,下一个单元格就永远不会被激活。结果是,您只需单击一次即可进行编辑,但任何不在网格上单击的用户都会感到不便,并且用户界面设计师不应假设所有用户都在使用鼠标。(键盘用户可以通过使用Tab来绕过它,但这仍然意味着他们正在经历他们不需要的困难。)

那么这个问题的解决方案呢?为单元格处理事件KeyDown,如果该键是Enter键,则设置一个标志,停止在第一个单元格上触发BeginEdit。现在,Enter键的行为与它应该的一样

首先,将以下样式添加到DataGrid:

<DataGrid.Resources>
    <Style TargetType="{x:Type DataGridCell}" x:Key="SingleClickEditingCellStyle">
        <EventSetter Event="KeyDown" Handler="DataGridCell_KeyDown" />
    </Style>
</DataGrid.Resources>
然后添加KeyDown事件的处理程序:

Private Sub DataGridCell_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
    If e.Key = Key.Enter Then
        Me._endEditing = True
    End If
End Sub
现在您有了一个DataGrid,它没有改变开箱即用实现的任何基本行为,但支持单击编辑。


public void ReachThisMethod(对象发送方)
{
((System.Windows.Controls.DataGridCell)(sender)).IsEditing=true;
}

我通过添加一个触发器解决了这个问题,当鼠标悬停在DataGridCell上时,该触发器将DataGridCell的IsEdit属性设置为True。它解决了我的大部分问题。它也适用于组合框

<Style TargetType="DataGridCell">
     <Style.Triggers>
         <Trigger Property="IsMouseOver" Value="True">
             <Setter Property="IsEditing" Value="True" />
         </Trigger>
     </Style.Triggers>
 </Style>

我更喜欢t
<DataGrid.Resources>

    <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
        <Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsMouseOver"
                                   Value="True" />
                        <Condition Property="IsReadOnly"
                                   Value="False" />
                    </MultiTrigger.Conditions>
                    <MultiTrigger.Setters>
                        <Setter Property="IsEditing"
                                Value="True" />
                    </MultiTrigger.Setters>
                </MultiTrigger>
        </Style.Triggers>
    </Style>

</DataGrid.Resources>
<UserControl xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:myBehavior="clr-namespace:My.Namespace.To.Behavior">

    <DataGrid>
        <i:Interaction.Behaviors>
            <myBehavior:EditCellOnSingleClickBehavior/>
        </i:Interaction.Behaviors>
    </DataGrid>
</UserControl>
public class EditCellOnSingleClick : Behavior<DataGrid>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.LoadingRow += this.OnLoadingRow;
        this.AssociatedObject.UnloadingRow += this.OnUnloading;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.LoadingRow -= this.OnLoadingRow;
        this.AssociatedObject.UnloadingRow -= this.OnUnloading;
    }

    private void OnLoadingRow(object sender, DataGridRowEventArgs e)
    {
        e.Row.GotFocus += this.OnGotFocus;
    }

    private void OnUnloading(object sender, DataGridRowEventArgs e)
    {
        e.Row.GotFocus -= this.OnGotFocus;
    }

    private void OnGotFocus(object sender, RoutedEventArgs e)
    {
        this.AssociatedObject.BeginEdit(e);
    }
}
     public class DataGridTextBoxColumn : DataGridBoundColumn
 {
  public DataGridTextBoxColumn():base()
  {
  }

  protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
  {
   throw new NotImplementedException("Should not be used.");
  }

  protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
  {
   var control = new TextBox();
   control.Style = (Style)Application.Current.TryFindResource("textBoxStyle");
   control.FontSize = 14;
   control.VerticalContentAlignment = VerticalAlignment.Center;
   BindingOperations.SetBinding(control, TextBox.TextProperty, Binding);
    control.IsReadOnly = IsReadOnly;
   return control;
  }
 }

        <DataGrid Grid.Row="1" x:Name="exportData" Margin="15" VerticalAlignment="Stretch" ItemsSource="{Binding CSVExportData}" Style="{StaticResource dataGridStyle}">
        <DataGrid.Columns >
            <local:DataGridTextBoxColumn Header="Sample ID" Binding="{Binding SampleID}" IsReadOnly="True"></local:DataGridTextBoxColumn>
            <local:DataGridTextBoxColumn Header="Analysis Date" Binding="{Binding Date}" IsReadOnly="True"></local:DataGridTextBoxColumn>
            <local:DataGridTextBoxColumn Header="Test" Binding="{Binding Test}" IsReadOnly="True"></local:DataGridTextBoxColumn>
            <local:DataGridTextBoxColumn Header="Comment" Binding="{Binding Comment}"></local:DataGridTextBoxColumn>
        </DataGrid.Columns>
    </DataGrid>
<DataGridTemplateColumn Header="My Column header">
   <DataGridTemplateColumn.CellTemplate>
      <DataTemplate>
         <TextBox Text="{Binding MyProperty } />
      </DataTemplate>
   </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<Window.Resources>
    <Style x:Key="SingleClickEditStyle" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
        <Setter Property="local:DataGridTextBoxSingleClickEditBehavior.Enable" Value="True" />
    </Style>
</Window.Resources>
<DataGrid ItemsSource="{Binding MyData}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="My Header" Binding="{Binding Comment}" CellStyle="{StaticResource SingleClickEditStyle}" />         
    </DataGrid.Columns>
</DataGrid>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace YourMainViewModelNameSpace
{
    public static class DataGridTextBoxSingleClickEditBehavior
    {
        public static readonly DependencyProperty EnableProperty = DependencyProperty.RegisterAttached(
            "Enable",
            typeof(bool),
            typeof(DataGridTextBoxSingleClickEditBehavior),
            new FrameworkPropertyMetadata(false, OnEnableChanged));


        public static bool GetEnable(FrameworkElement frameworkElement)
        {
            return (bool) frameworkElement.GetValue(EnableProperty);
        }


        public static void SetEnable(FrameworkElement frameworkElement, bool value)
        {
            frameworkElement.SetValue(EnableProperty, value);
        }


        private static void OnEnableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is DataGridCell dataGridCell)
                dataGridCell.PreviewMouseLeftButtonDown += DataGridCell_PreviewMouseLeftButtonDown;
        }


        private static void DataGridCell_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            EditCell(sender as DataGridCell, e);
        }

        private static void EditCell(DataGridCell dataGridCell, RoutedEventArgs e)
        {
            if (dataGridCell == null || dataGridCell.IsEditing || dataGridCell.IsReadOnly)
                return;

            if (dataGridCell.IsFocused == false)
                dataGridCell.Focus();

            var dataGrid = FindVisualParent<DataGrid>(dataGridCell);
            dataGrid?.BeginEdit(e);
        }


        private static T FindVisualParent<T>(UIElement element) where T : UIElement
        {
            var parent = VisualTreeHelper.GetParent(element) as UIElement;

            while (parent != null)
            {
                if (parent is T parentWithCorrectType)
                    return parentWithCorrectType;

                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }

            return null;
        }
    }
}
<DataGrid.Resources>
   <Style x:Key="ddlStyle" TargetType="DataGridCell">
      <Style.Triggers>
         <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="IsEditing" Value="True" />
         </Trigger>
      </Style.Triggers>
    </Style>
</DataGrid.Resources>
<DataGridComboBoxColumn CellStyle="{StaticResource ddlStyle}">