2010-07-14 22 views

Trả lời

5

Ok, tôi havent tìm thấy một giải pháp đơn giản và không ai chỉ cho tôi một. Đoạn mã sau có thể được sử dụng để thêm một thuộc tính đính kèm IsInEditMode vào một DataGrid. Hy vọng nó sẽ giúp ai đó:

public class DataGridIsInEditModeTracker { 

    public static bool GetIsInEditMode(DataGrid dataGrid) { 
     return (bool)dataGrid.GetValue(IsInEditModeProperty); 
    } 

    private static void SetIsInEditMode(DataGrid dataGrid, bool value) { 
     dataGrid.SetValue(IsInEditModePropertyKey, value); 
    } 

    private static readonly DependencyPropertyKey IsInEditModePropertyKey = DependencyProperty.RegisterAttachedReadOnly("IsInEditMode", typeof(bool), typeof(DataGridIsInEditModeTracker), new UIPropertyMetadata(false)); 

    public static readonly DependencyProperty IsInEditModeProperty = IsInEditModePropertyKey.DependencyProperty; 


    public static bool GetProcessIsInEditMode(DataGrid dataGrid) { 
     return (bool)dataGrid.GetValue(ProcessIsInEditModeProperty); 
    } 

    public static void SetProcessIsInEditMode(DataGrid dataGrid, bool value) { 
     dataGrid.SetValue(ProcessIsInEditModeProperty, value); 
    } 


    public static readonly DependencyProperty ProcessIsInEditModeProperty = 
     DependencyProperty.RegisterAttached("ProcessIsInEditMode", typeof(bool), typeof(DataGridIsInEditModeTracker), new FrameworkPropertyMetadata(false, delegate(DependencyObject d,DependencyPropertyChangedEventArgs e) { 

      DataGrid dataGrid = d as DataGrid; 
      if (null == dataGrid) { 
       throw new InvalidOperationException("ProcessIsInEditMode can only be used with instances of the DataGrid-class"); 
      } 
      if ((bool)e.NewValue) { 
       dataGrid.BeginningEdit += new EventHandler<DataGridBeginningEditEventArgs>(dataGrid_BeginningEdit); 
       dataGrid.CellEditEnding += new EventHandler<DataGridCellEditEndingEventArgs>(dataGrid_CellEditEnding); 
      } else { 
       dataGrid.BeginningEdit -= new EventHandler<DataGridBeginningEditEventArgs>(dataGrid_BeginningEdit); 
       dataGrid.CellEditEnding -= new EventHandler<DataGridCellEditEndingEventArgs>(dataGrid_CellEditEnding); 
      } 
     })); 

    static void dataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) {    
     SetIsInEditMode((DataGrid)sender,false); 
    } 

    static void dataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e) { 
     SetIsInEditMode((DataGrid)sender, true); 
    }     
} 

Để sử dụng nó, đặt trên DataGrid tài sản ProcessIsInEditMode- true:

<DataGrid local:DataGridIsInEditModeTracker.ProcessIsInEditMode="True" .. other properties ..> 

Afer rằng bạn sẽ có IsInEditMode-bất động sản đồng bộ với chế độ của Lưới dữ liệu. Nếu bạn cũng muốn ô chỉnh sửa, hãy thay đổi mã trong BeginningEdit accoringly.

+0

Tuyệt vời, cảm ơn, cho ý kiến ​​của tôi bạn nên đăng bài này trong một kết nối với Microsoft và đăng ở đây một liên kết để người dùng có thể bỏ phiếu cho nó được thực hiện out-the-box trong phiên bản sắp tới. – Shimmy

+0

Tôi sẽ đề nghị thay thế các tham số obendendencyProperty obj bằng DataGrid dg, vì vậy thuộc tính đính kèm chỉ có thể được áp dụng cho các đối tượng kiểu DataGrid. – Shimmy

+0

Bạn nói đúng - tôi đã thay đổi nó. – HCL

3

Tôi tìm thấy một workaround ngắn hơn (VB.NET/C#):

VB.NET

<Extension> 
Public Function GetContainerFromIndex(Of TContainer As DependencyObject) _ 
    (ByVal itemsControl As ItemsControl, ByVal index As Integer) As TContainer 
    Return DirectCast(
    itemsControl.ItemContainerGenerator.ContainerFromIndex(index), TContainer) 
End Function 

<Extension> 
Public Function IsEditing(ByVal dataGrid As DataGrid) As Boolean 
    Return dataGrid.GetEditingRow IsNot Nothing 
End Function 

<Extension> 
Public Function GetEditingRow(ByVal dataGrid As DataGrid) As DataGridRow 
    Dim sIndex = dataGrid.SelectedIndex 
    If sIndex >= 0 Then 
    Dim selected = dataGrid.GetContainerFromIndex(Of DataGridRow)(sIndex) 
    If selected.IsEditing Then Return selected 
    End If 

    For i = 0 To dataGrid.Items.Count - 1 
    If i = sIndex Then Continue For 
    Dim item = dataGrid.GetContainerFromIndex(Of DataGridRow)(i) 
    If item.IsEditing Then Return item 
    Next 

    Return Nothing 
End Function 

C#:

public static TContainer GetContainerFromIndex<TContainer> 
    (this ItemsControl itemsControl, int index) 
    where TContainer : DependencyObject 
{ 
    return (TContainer) 
    itemsControl.ItemContainerGenerator.ContainerFromIndex(index); 
} 

public static bool IsEditing(this DataGrid dataGrid) 
{ 
    return dataGrid.GetEditingRow() != null; 
} 

public static DataGridRow GetEditingRow(this DataGrid dataGrid) 
{ 
    var sIndex = dataGrid.SelectedIndex; 
    if (sIndex >= 0) 
    { 
    var selected = dataGrid.GetContainerFromIndex<DataGridRow>(sIndex); 
    if (selected.IsEditing) return selected; 
    } 

    for (int i = 0; i < dataGrid.Items.Count; i++) 
    { 
    if (i == sIndex) continue; 
    var item = dataGrid.GetContainerFromIndex<DataGridRow>(i); 
    if (item.IsEditing) return item; 
    } 

    return null; 
} 
+0

Đôi khi GetContainerFromIndex không trả lại giá trị. Tôi không chắc chắn nếu nó có cái gì để làm với các mục ảo/không được tạo ra. Vì vậy item.IsEditing trong GetEditingRow gây ra một NullReferenceException. Nhưng dù sao; đây là điều nhỏ nhặt và bạn đã giải quyết được sự cố của mình: +1 – Markus

+0

@Markus nếu bạn đã từng tìm thấy một dấu vết cho điều đó, vui lòng buzz – Shimmy

7

Có vẻ như bạn cũng có thể nhận được thông tin này từ mục xem, cụ thể là công trình này:

IEditableCollectionView itemsView = stateGrid.Items; 
if (itemsView.IsAddingNew || itemsView.IsEditingItem) 
{ 
    stateGrid.CommitEdit(DataGridEditingUnit.Row, true); 
} 

Tôi đã không xác nhận điều này nhưng rất có thể bạn có thể nhận được những lá cờ này trong một viewmodel nếu bộ sưu tập bị ràng buộc của bạn cung cấp một IEditableCollectionView.

0

Tất cả các câu trả lời ở trên sử dụng IsEditing trên datagridrow hoặc IsEdititngItem trên IEditableCollectionView là câu trả lời một phần với tôi:

Nếu người dùng nhập phiên bản, sau đó clics trên bất kỳ tế bào khác, sự kiện EndEdit là bắn nhưng DataGridRow có vẫn là tài sản IsEditing to True !!! Và nếu bạn cố gắng tìm DataGridCell chịu trách nhiệm, IsEditingProperty của nó luôn luôn là sai ... Tôi nghĩ rằng đó là một lỗi. Và để có hành vi mong muốn, tôi đã phải viết workaround Ugly này

Public Shared ReadOnly ForceEndEditProp As DependencyProperty = 
     DependencyProperty.RegisterAttached("ForceEndEdit", GetType(Boolean), 
     GetType(DataGridEditing), New PropertyMetadata(False, AddressOf ForceEndEditChanged)) 

Protected Shared Sub ForceEndEditChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs) 
    Dim g As DataGrid = TryCast(d, DataGrid) 
    If g Is Nothing Then Return 
    ''IsCommiting prevents a StackOverflow ... 
    Dim IsCommiting As Boolean = False 
    AddHandler g.CellEditEnding, Sub(s, e1) 
            If IsCommiting Then Return 
            IsCommiting = True 
            g.CommitEdit(DataGridEditingUnit.Row, True) 
            IsCommiting = False 
           End Sub 
End Sub 

Public Shared Function GetForceEndEdit(o As DependencyObject) As Boolean 
    Return o.GetValue(ForceEndEditProp) 
End Function 

Public Shared Sub SetForceEndEdit(ByVal o As DependencyObject, ByVal value As Boolean) 
    o.SetValue(ForceEndEditProp, value) 
End Sub 

này về cơ bản buộc các lưới để đặt IsEditing = false trên datagridrow, khi bất kỳ tế bào dừng lại chỉnh sửa.

Các vấn đề liên quan