คลิกเดียวแก้ไขใน WPF DataGrid


92

ฉันต้องการให้ผู้ใช้สามารถนำเซลล์เข้าสู่โหมดแก้ไขและไฮไลต์แถวที่เซลล์นั้นอยู่ในคลิกเดียว ตามค่าเริ่มต้นนี่คือดับเบิลคลิก

ฉันจะลบล้างหรือใช้สิ่งนี้ได้อย่างไร


คุณใช้ DataGrid ที่พบใน WPF Toolkit หรือไม่
myermian

4
เป็นไปได้หรือไม่ที่คุณจะให้ข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่คุณได้ลองใช้และวิธีการที่ไม่ได้ผล
Zach Johnson

คำตอบ:


76

นี่คือวิธีที่ฉันแก้ไขปัญหานี้:

<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 (มีวัตถุบุคคลจำลอง)

ความมหัศจรรย์ที่เกิดขึ้นที่นั่นDataGridCell.Selected = "DataGridCell_Selected"

ฉันเพียงแค่เชื่อมโยงเหตุการณ์ที่เลือกของเซลล์ DataGrid และเรียก BeginEdit () บน DataGrid

นี่คือรหัสเบื้องหลังสำหรับตัวจัดการเหตุการณ์:

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

8
คุณจะได้รับการแก้ไขปัญหาแถวแล้วเลือกโดยการตั้งค่าSelectionUnitสถานที่ให้บริการใน DataGrid Cellไป
Matt Winckler

สมมติว่าฉันมีกล่องข้อความใน DataGridCell หลังจากที่ฉันโทรgrd.BeginEdit(e)ฉันต้องการให้กล่องข้อความในเซลล์นั้นมีโฟกัส ฉันจะทำเช่นนั้นได้อย่างไร? ฉันพยายามเรียกFindName("txtBox")ทั้ง DataGridCell และ DataGrid แต่มันกลับเป็นโมฆะสำหรับฉัน
user1214135

GotFocus = "DataGrid_GotFocus" ดูเหมือนจะหายไป?
synergetic

4
วิธีนี้ใช้ได้ดี แต่ฉันไม่แนะนำให้ทำเช่นนี้ ฉันได้ใช้สิ่งนี้ในโครงการของฉันและตัดสินใจที่จะย้อนกลับไปใช้พฤติกรรม DG มาตรฐาน ในอนาคตเมื่อ DG ของคุณเติบโตและซับซ้อนคุณจะพบปัญหาเกี่ยวกับการตรวจสอบความถูกต้องการเพิ่มแถวใหม่และพฤติกรรมแปลก ๆ อื่น ๆ
white.zaz

1
@ white.zaz ลูกค้ามีความสุขหลังจากที่คุณย้อนกลับไปสู่พฤติกรรม DG มาตรฐานหรือไม่? เนื่องจากเหตุผลหลักที่ถามคำถามนี้คือการแก้ไขในความสามารถ DG มาตรฐานนั้นไม่เป็นมิตรกับผู้ใช้เนื่องจากต้องคลิกหลายครั้งเกินไปก่อนที่ DG จะเข้าสู่โหมดแก้ไข
AEMLoviji

42

คำตอบจาก Micael Bergeron เป็นการเริ่มต้นที่ดีสำหรับฉันในการหาวิธีแก้ปัญหาที่เหมาะกับฉัน เพื่อให้สามารถแก้ไขด้วยคลิกเดียวสำหรับเซลล์ในแถวเดียวกันกับที่อยู่ในโหมดแก้ไขแล้วฉันต้องปรับแต่งเล็กน้อย การใช้ SelectionUnit Cell ไม่ใช่ตัวเลือกสำหรับฉัน

แทนที่จะใช้ DataGridCell.Selected Event ซึ่งจะเริ่มทำงานเพียงครั้งแรกที่มีการคลิกเซลล์ของแถวฉันใช้ DataGridCell.GotFocus Event

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

3
ช่องทำเครื่องหมายดูเหมือนจะใช้ไม่ได้สำหรับฉัน? ฉันยังต้องดับเบิลคลิกพวกเขา
Thomas Klammer

9

จาก: 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;
}

1
สิ่งนี้ใช้ไม่ได้ในบางกรณีและโซลูชัน Micael Bergerons ที่ซับซ้อนกว่านั้น
SwissCoder

สำหรับฉันนี่เกือบจะเป็นทางออก ฉันต้องการเพิ่มตัวจัดการเหตุการณ์ "PreviewMouseLeftButtonUp" และใส่รหัสเดียวกันทุกประการ
NéstorSánchez A.

สิ่งนี้จะใช้ไม่ได้เมื่อคุณมีคอมโบบ็อกซ์เช่นกัน การคลิกดูตัวอย่างจะเห็นการคลิกบนป๊อปอัปของคอมโบบ็อกซ์จากนั้นการโทรของเซลล์โฟกัสจะสกรูทุกอย่าง การแก้ไขที่ง่ายที่สุดคือการเพิ่มส่วนที่ดูแหล่งที่มาดั้งเดิมของเหตุการณ์ของเมาส์โดยใช้ FindVisualParent เพื่อดูว่าอยู่ในดาต้ากริดหรือไม่ ถ้าไม่อย่าทำงานอื่น ๆ
John Gardner

7

วิธีแก้ปัญหาจากhttp://wpf.codeplex.com/wikipage?title=Single-Click%20Editingทำงานได้ดีสำหรับฉัน แต่ฉันเปิดใช้งานสำหรับทุก DataGrid โดยใช้ Style ที่กำหนดใน ResourceDictionary หากต้องการใช้ตัวจัดการในพจนานุกรมทรัพยากรคุณต้องเพิ่มไฟล์รหัสหลังเข้าไป นี่คือวิธีที่คุณทำ:

นี่คือพจนานุกรมทรัพยากร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.
}

ลิงค์ตาย (จำกัด อักขระ 15 ตัว)
Blechdose

4

ฉันชอบวิธีนี้ตามคำแนะนำของDušanKnež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>

สิ่งนี้ใช้ไม่ได้หากใช้คอมโบบ็อกซ์เป็นเทมเพลตการแก้ไขฉันจะถือว่าคนอื่น ๆ เช่นกล่องกาเครื่องหมายที่จับเหตุการณ์เมาส์จะพังเช่นกัน
สตีฟ

สำหรับฉันสิ่งนี้ใช้ได้กับ Combobox Columns แต่ Textbox ของ "บรรทัดรายการใหม่" (บรรทัดสุดท้าย) มีพฤติกรรมแปลก ๆ : เมื่อคลิกครั้งแรกฉันจะได้รับโฟกัสอินพุตและสามารถพิมพ์สิ่งต่างๆได้เมื่อฉันเลื่อนเมาส์ออกจากเซลล์ ค่าของกล่องข้อความจะหายไป เมื่อพิมพ์ต่อไปข้อความที่ป้อนใหม่จะถูกบันทึกอย่างถูกต้อง (จะสร้างรายการใหม่ตามที่ต้องการ) สิ่งนี้เกิดขึ้นได้แม้กับ ComboboxColumn ด้วย
FrankM

ตอนแรกดูเหมือนจะทำงานได้ดี แต่ทำให้ Datagrid ของฉันยุ่งเหยิงโดยสิ้นเชิงเมื่อฉันพยายามจัดเรียงค่าทั้งหมดเหล่านี้จะหายไปโดยไม่มีรหัสนี้ทุกอย่างทำงานได้ดีกับการเรียงลำดับ
Chandraprakash

3

ฉันแก้ไขได้โดยการเพิ่มทริกเกอร์ที่ตั้งค่าคุณสมบัติ IsEditing ของ DataGridCell เป็น True เมื่อเมาส์อยู่เหนือมัน มันแก้ปัญหาส่วนใหญ่ของฉันได้ มันทำงานร่วมกับ comboboxes ด้วย

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

1
ไม่ทำงาน ... มันจะสูญเสียการแก้ไขทันทีที่เมาส์ออกจากเซลล์ คุณจึง 1) คลิกซ้ายที่เซลล์ที่คุณต้องการแก้ไข 2) เลื่อนเมาส์ออกไปให้พ้นทาง 3) เริ่มพิมพ์ การพิมพ์ของคุณไม่ทำงานเนื่องจากเซลล์ไม่ได้อยู่ในโหมดแก้ไขอีกต่อไป
Skarsnik

1
ไม่ได้ผลสำหรับฉันเช่นกัน ป้องกันไม่ให้แก้ไข textbox สำหรับฉัน
Blechdose

แต่มีปัญหาอย่างหนึ่งในแนวทางนี้ฉันได้ล็อกคอลัมน์ที่ 1 ไว้เพื่อแก้ไขด้วยวิธีนี้ทำให้คอลัมน์ที่ 1 สามารถแก้ไขได้ด้วย!
Chandraprakash

3

ฉันกำลังมองหาการแก้ไขเซลล์ด้วยการคลิกเพียงครั้งเดียวใน 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);
        }
    }
    

โวลา!


1

คำตอบของ user2134678 มีสองประเด็น หนึ่งน้อยมากและไม่มีผลการทำงาน อีกประการหนึ่งมีความสำคัญพอสมควร

ประเด็นแรกคือ GotFocus ถูกเรียกให้ต่อต้าน DataGrid ไม่ใช่ DataGridCell ในทางปฏิบัติ DataGridCell qualifier ใน XAML ซ้ำซ้อน

ปัญหาหลักที่ฉันพบกับคำตอบคือการทำงานของคีย์ Enter เสีย Enter ควรย้ายคุณไปยังเซลล์ถัดไปด้านล่างเซลล์ปัจจุบันในลักษณะการทำงานของ DataGrid ปกติ อย่างไรก็ตามสิ่งที่เกิดขึ้นจริงเบื้องหลังคือเหตุการณ์ GotFocus จะถูกเรียกสองครั้ง เมื่อเซลล์ปัจจุบันสูญเสียโฟกัสและเมื่อเซลล์ใหม่ได้รับโฟกัส แต่ตราบใดที่มีการเรียกใช้ BeginEdit ในเซลล์แรกนั้นเซลล์ถัดไปจะไม่ถูกเปิดใช้งาน ผลลัพธ์คือคุณมีการแก้ไขด้วยคลิกเดียว แต่ใครก็ตามที่ไม่ได้คลิกบนกริดจริงๆจะไม่สะดวกและผู้ออกแบบส่วนต่อประสานผู้ใช้ไม่ควรคิดว่าผู้ใช้ทั้งหมดกำลังใช้ mouses (ผู้ใช้แป้นพิมพ์สามารถจัดการกับมันได้โดยใช้ Tab แต่นั่นก็หมายความว่าพวกเขากำลังกระโดดผ่านห่วงที่พวกเขาไม่จำเป็นต้องทำ)

วิธีแก้ปัญหานี้? จัดการเหตุการณ์ KeyDown สำหรับเซลล์และถ้า Key เป็นคีย์ Enter ให้ตั้งค่าสถานะที่หยุด BeginEdit ไม่ให้เริ่มทำงานในเซลล์แรก ตอนนี้ปุ่ม Enter ทำงานตามที่ควร

เริ่มต้นด้วยการเพิ่มสไตล์ต่อไปนี้ใน DataGrid ของคุณ:

<DataGrid.Resources>
    <Style TargetType="{x:Type DataGridCell}" x:Key="SingleClickEditingCellStyle">
        <EventSetter Event="KeyDown" Handler="DataGridCell_KeyDown" />
    </Style>
</DataGrid.Resources>

ใช้สไตล์นั้นกับคุณสมบัติ "CellStyle" คอลัมน์ที่คุณต้องการเปิดใช้งานในคลิกเดียว

จากนั้นในโค้ดด้านหลังคุณจะมีสิ่งต่อไปนี้ในตัวจัดการ GotFocus ของคุณ (โปรดทราบว่าฉันใช้ VB ที่นี่เพราะนั่นคือสิ่งที่ไคลเอ็นต์ "ขอข้อมูลแบบคลิกเดียว" ของเราต้องการเป็นภาษาสำหรับการพัฒนา):

Private _endEditing As Boolean = False

Private Sub DataGrid_GotFocus(ByVal sender As Object, ByVal e As RoutedEventArgs)
    If Me._endEditing Then
        Me._endEditing = False
        Return
    End If

    Dim cell = TryCast(e.OriginalSource, DataGridCell)

    If cell Is Nothing Then
        Return
    End If

    If cell.IsReadOnly Then
        Return
    End If

    DirectCast(sender, DataGrid).BeginEdit(e)
    .
    .
    .

จากนั้นคุณเพิ่มตัวจัดการของคุณสำหรับเหตุการณ์ 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 ที่ไม่ได้เปลี่ยนพฤติกรรมพื้นฐานใด ๆ ของการใช้งานนอกกรอบและยังรองรับการแก้ไขด้วยคลิกเดียว


0

ฉันรู้ว่าฉันไปงานปาร์ตี้ช้าไปหน่อย แต่ฉันมีปัญหาเดียวกันและหาวิธีแก้ปัญหาอื่น:

     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>

อย่างที่คุณเห็นฉันเขียน DataGridTextColumn ของตัวเองที่สืบทอดทุกสิ่งที่ทำให้ DataGridBoundColumn อาเจียน โดยการแทนที่ GenerateElement Method และส่งคืนตัวควบคุม Textbox ที่นั่นจะทำให้ Method สำหรับการสร้าง Editing Element ไม่เคยถูกเรียก ในโครงการอื่นฉันใช้สิ่งนี้เพื่อติดตั้งคอลัมน์ Datepicker ดังนั้นสิ่งนี้ควรใช้ได้กับช่องทำเครื่องหมายและกล่องคอมโบด้วย

สิ่งนี้ดูเหมือนจะไม่ส่งผลกระทบต่อพฤติกรรมของดาต้ากริดที่เหลือ .. อย่างน้อยฉันก็ยังไม่สังเกตเห็นผลข้างเคียงใด ๆ และจนถึงตอนนี้ฉันยังไม่ได้รับข้อเสนอแนะเชิงลบใด ๆ


-1

อัปเดต

วิธีแก้ปัญหาง่ายๆหากคุณพอใจกับการที่เซลล์ของคุณยังคงเป็นช่องข้อความ (ไม่มีการแยกแยะระหว่างโหมดแก้ไขและโหมดไม่แก้ไข) การแก้ไขด้วยการคลิกเพียงครั้งเดียวนี้ทำงานได้ทันที สิ่งนี้ใช้ได้กับองค์ประกอบอื่น ๆ เช่นคอมโบบ็อกซ์และปุ่มเช่นกัน มิฉะนั้นให้ใช้วิธีแก้ไขปัญหาด้านล่างการอัปเดต

<DataGridTemplateColumn Header="My Column header">
   <DataGridTemplateColumn.CellTemplate>
      <DataTemplate>
         <TextBox Text="{Binding MyProperty } />
      </DataTemplate>
   </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

สิ้นสุดการอัปเดต

พูดจาโผงผาง

ฉันลองทุกอย่างที่พบที่นี่และใน Google และแม้แต่ลองสร้างเวอร์ชันของตัวเอง แต่ทุกคำตอบ / วิธีแก้ปัญหาทำงานกับคอลัมน์กล่องข้อความเป็นหลัก แต่ใช้ไม่ได้กับองค์ประกอบอื่น ๆ ทั้งหมด (ช่องทำเครื่องหมายคอมโบบ็อกซ์คอลัมน์ปุ่ม) หรือแม้แต่ทำให้คอลัมน์องค์ประกอบอื่น ๆ เสียหายหรือมีผลข้างเคียงอื่น ๆ ขอบคุณไมโครซอฟท์ที่ทำให้ดาต้ากริดมีพฤติกรรมที่น่าเกลียดและบังคับให้เราสร้างแฮ็กเหล่านั้น ด้วยเหตุนี้ฉันจึงตัดสินใจสร้างเวอร์ชันที่สามารถใช้กับสไตล์กับคอลัมน์กล่องข้อความได้โดยตรงโดยไม่ส่งผลกระทบต่อคอลัมน์อื่น ๆ

คุณสมบัติ

  • ไม่มีรหัสหลัง เป็นมิตรกับ MVVM
  • ทำงานเมื่อคลิกที่เซลล์กล่องข้อความต่างๆในแถวเดียวกันหรือต่างกัน
  • แป้น TAB และ ENTER ใช้งานได้
  • ไม่มีผลต่อคอลัมน์อื่น ๆ

แหล่งที่มา

ฉันใช้วิธีแก้ปัญหานี้และคำตอบของ @ และแก้ไขให้เป็นพฤติกรรมที่แนบมา http://wpf-tutorial-net.blogspot.com/2016/05/wpf-datagrid-edit-cell-on-single-click.html

วิธีการใช้งาน

เพิ่มรูปแบบนี้ สิ่งBasedOnนี้สำคัญเมื่อคุณใช้สไตล์แฟนซีสำหรับดาต้ากริดของคุณและคุณไม่อยากเสียมันไป

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

ใช้สไตล์กับCellStyleแต่ละแบบของคุณDataGridTextColumnsดังนี้:

<DataGrid ItemsSource="{Binding MyData}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="My Header" Binding="{Binding Comment}" CellStyle="{StaticResource SingleClickEditStyle}" />         
    </DataGrid.Columns>
</DataGrid>

และตอนนี้เพิ่มคลาสนี้ในเนมสเปซเดียวกับ MainViewModel ของคุณ (หรือเนมสเปซอื่น แต่คุณจะต้องใช้คำนำหน้าเนมสเปซอื่นที่ไม่ใช่local) ยินดีต้อนรับสู่โลกแห่งรหัสต้นแบบที่น่าเกลียดของพฤติกรรมที่แนบมา

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

-3
 <DataGridComboBoxColumn.CellStyle>
                        <Style TargetType="DataGridCell">
                            <Setter Property="cal:Message.Attach" 
                            Value="[Event MouseLeftButtonUp] = [Action ReachThisMethod($source)]"/>
                        </Style>
                    </DataGridComboBoxColumn.CellStyle>
 public void ReachThisMethod(object sender)
 {
     ((System.Windows.Controls.DataGridCell)(sender)).IsEditing = true;

 }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.