[c#] WPF DataGrid에서 한 번의 클릭으로 편집

사용자가 셀을 편집 모드로 전환하고 한 번의 클릭으로 셀이 포함 된 행을 강조 표시 할 수 있기를 바랍니다. 기본적으로 두 번 클릭합니다.

이것을 재정의하거나 구현하려면 어떻게해야합니까?



답변

이 문제를 해결 한 방법은 다음과 같습니다.

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

이 DataGrid는 CollectionViewSource (더미 Person 개체 포함)에 바인딩됩니다 .

마술은 거기에서 일어난다 : DataGridCell.Selected = “DataGridCell_Selected” .

DataGrid 셀의 Selected Event를 연결하고 DataGrid에서 BeginEdit ()를 호출합니다.

다음은 이벤트 처리기의 코드입니다.

private void DataGridCell_Selected(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);
    }
}


답변

Micael Bergeron의 답변은 저에게 적합한 솔루션을 찾는 좋은 출발점이되었습니다. 이미 편집 모드에있는 동일한 행의 셀에 대해서도 한 번 클릭 편집을 허용하려면 약간 조정해야했습니다. SelectionUnit Cell을 사용하는 것은 나에게 옵션이 아닙니다.

행의 셀을 처음 클릭했을 때만 발생하는 DataGridCell.Selected 이벤트를 사용하는 대신 DataGridCell.GotFocus 이벤트를 사용했습니다.

<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;
}


답변

From : http://wpf.codeplex.com/wikipage?title=Single-Click%20Editing

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;
}


답변

http://wpf.codeplex.com/wikipage?title=Single-Click%20Editing 의 솔루션은 저에게 잘 맞았지만 ResourceDictionary에 정의 된 Style을 사용하여 모든 DataGrid에 대해 활성화했습니다. 리소스 사전에서 핸들러를 사용하려면 여기에 코드 숨김 파일을 추가해야합니다. 방법은 다음과 같습니다.

다음은 DataGridStyles.xaml 리소스 사전입니다.

    <ResourceDictionary x:Class="YourNamespace.DataGridStyles"
                x:ClassModifier="public"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Style TargetType="DataGrid">
            <!-- Your DataGrid style definition goes here -->

            <!-- Cell style -->
            <Setter Property="CellStyle">
                <Setter.Value>
                    <Style TargetType="DataGridCell">
                        <!-- Your DataGrid Cell style definition goes here -->
                        <!-- Single Click Editing -->
                        <EventSetter Event="PreviewMouseLeftButtonDown"
                                 Handler="DataGridCell_PreviewMouseLeftButtonDown" />
                    </Style>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>

루트 요소의 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.
}


답변

나는 Dušan Knežević의 제안에 따라이 방법을 선호합니다. 그게 다입니다))

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


답변

마우스가 위에있을 때 DataGridCell의 IsEditing 속성을 True로 설정하는 트리거를 추가하여 문제를 해결했습니다. 그것은 내 문제의 대부분을 해결했습니다. 콤보 박스에서도 작동합니다.

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


답변

MVVM에서 한 번의 클릭으로 편집 셀을 찾고 있는데 이것은 다른 방법입니다.

  1. xaml에 동작 추가

    <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>
    
  2. EditCellOnSingleClickBehavior 클래스는 System.Windows.Interactivity.Behavior를 확장합니다.

    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);
        }
    }
    

짜잔!