2010-01-13 23 views

Trả lời

3

Điều này không được hỗ trợ trong DataGrid trong bộ công cụ, và có vẻ như nó won't be supported khi DataGrid được vận chuyển với .NET 4. Tuy nhiên, một lý do khác tại sao sự kiểm soát này không sẵn sàng cho việc sử dụng sản xuất. Tôi sẽ đi với một trong các tùy chọn này:

  1. cuộn lưới của riêng bạn với ListView/GridView
  2. Sửa đổi mã nguồn của DataGrid trong bộ công cụ (nó không nên quá khắt khe từ lựa chọn mở rộng đã được hỗ trợ ?)
  3. Hãy tìm bất kỳ của lưới dữ liệu sủ WPF thương mại có sẵn (họ thường thêm số tiền rất lớn của các chức năng hữu ích)

tôi đồng ý rằng DataGrid nên hỗ trợ này và tôi nghĩ bạn nên file a bug/suggestion cho điều này anyway. Có lẽ nó không quá muộn để làm cho nó vào NET 4 .. :)

3

Bạn có thể thử phương pháp đơn giản này mà không cần phải sửa đổi/kế thừa DataGrid kiểm soát bằng cách xử lý preview chuột xuống sự kiện như sau:

TheDataGrid.PreviewMouseLeftButtonDown += 
       new MouseButtonEventHandler(TheDataGrid_PreviewMouseLeftButtonDown); 


void TheDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    // get the DataGridRow at the clicked point 
    var o = TryFindFromPoint<DataGridRow>(TheDataGrid, e.GetPosition(TheDataGrid)); 
    // only handle this when Ctrl or Shift not pressed 
    ModifierKeys mods = Keyboard.PrimaryDevice.Modifiers; 
    if (o != null && ((int)(mods & ModifierKeys.Control) == 0 && 
               (int)(mods & ModifierKeys.Shift) == 0)) 
    { 
     o.IsSelected = !o.IsSelected; 
     e.Handled = true; 
    } 
} 

public static T TryFindFromPoint<T>(UIElement reference, Point point) 
       where T:DependencyObject 
{ 
    DependencyObject element = reference.InputHitTest(point) as DependencyObject; 
    if (element == null) 
     return null; 
    else if (element is T) 
     return (T)element; 
    else return TryFindParent<T>(element); 
} 

Phương pháp TryFindFromPoint, từ một số blog post by Philipp Sumi, được sử dụng để lấy trường hợp DataGridRow từ điểm bạn đã nhấp.

Bằng cách kiểm tra ModifierKeys, bạn vẫn có thể giữ Ctrl và Shift làm hành vi mặc định.

Chỉ một điểm vẽ từ phương pháp này là bạn không thể nhấp và kéo để thực hiện phạm vi được chọn giống như ban đầu.

10

Tôi đã tạo một ứng dụng có yêu cầu tương tự sẽ hoạt động cho cả màn hình cảm ứng và máy tính để bàn. Sau khi dành chút thời gian cho nó, giải pháp tôi đưa ra có vẻ sạch hơn. Trong nhà thiết kế, tôi đã thêm các setters sự kiện sau đây để DataGrid:

<DataGrid.RowStyle> 
    <Style TargetType="DataGridRow" > 
    <EventSetter Event="MouseEnter" Handler="MouseEnterHandler"></EventSetter> 
    <EventSetter Event="PreviewMouseDown" Handler="PreviewMouseDownHandler"></EventSetter> 
    </Style> 
</DataGrid.RowStyle> 

Sau đó, trong codebehind, tôi xử lý các sự kiện như:

private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e) 
{ 
    if (e.LeftButton == MouseButtonState.Pressed) 
    { 
     DataGridRow row = Utility.GetVisualParentByType(
        (FrameworkElement)e.OriginalSource, typeof(DataGridRow)) as DataGridRow; 

     row.IsSelected = !row.IsSelected; 
     e.Handled = true; 
    } 
} 

private void MouseEnterHandler(object sender, MouseEventArgs e) 
{ 
    if (e.OriginalSource is DataGridRow && e.LeftButton == MouseButtonState.Pressed) 
    { 
     DataGridRow row = e.OriginalSource as DataGridRow; 

     row.IsSelected = !row.IsSelected; 
     e.Handled = true; 
    } 
} 

Đây là mã cho phương thức helper GetVisualParentByType:

public static DependencyObject GetVisualParentByType(DependencyObject startObject, Type type) 
{ 
    DependencyObject parent = startObject; 
    while (parent != null) 
    { 
     if (type.IsInstanceOfType(parent)) 
      break; 
     else 
      parent = VisualTreeHelper.GetParent(parent); 
    } 

    return parent; 
} 

Hy vọng nó cũng giúp người khác.

0

Dựa trên một bài viết trước, tôi đã viết một ("like") mã MVVM:

Thứ nhất thêm video này vào Xem chính của bạn:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 

Phần liên quan của Xem:

 <DataGrid 
       Style="{StaticResource DataGridStyle}" 
       ItemsSource="{Binding Results}" 
       SelectionUnit="FullRow" 
       SnapsToDevicePixels="True" 
       SelectionMode="Extended"> <!--You can change selection mode with converter. It will work (i tested it.)--> 
     <i:Interaction.Behaviors> 
         <utils:EventToCommandBehavior Command="{Binding TouchCommand}" 
                Event="PreviewTouchDown" 
                PassArguments="True"></utils:EventToCommandBehavior> 
         <utils:EventToCommandBehavior Command="{Binding MouseCommand}" 
                Event="PreviewMouseDown" 
                PassArguments="True"></utils:EventToCommandBehavior> 
     </i:Interaction.Behaviors> 
     <DataGrid.Resources> 
      <Style TargetType="{x:Type DataGridRow}"> 
       <Setter Property="IsSelected"<Style.Triggers> 
        <Trigger Property="IsSelected" Value="True"> 
         <Setter Property="Background"> 
          <Setter.Value> 
           <SolidColorBrush> 
            <SolidColorBrush.Color> 
             <Color A="50" R="0" G="0" B="0" /> 
            </SolidColorBrush.Color> 
           </SolidColorBrush> 
          </Setter.Value> 
         </Setter> 
        </Trigger> 
       </Style.Triggers> 
      </Style> 
      </DataGrid.Resources> 
     <DataGrid.Columns> 
     <!-- your columns --> 
     </DataGrid.Columns> 
     </DataGrid> 

Thông tin khác về EventToCommandBehavior: here

Bằng cách này, ViewModel của bạn phải thực hiện các lệnh:

//i skipped the TouchCommand definition because MouseCommand runs for touch on screen too. 
    public RelayCommand<MouseButtonEventArgs> MouseCommand 
    { 
     get 
     { 
      return new RelayCommand<MouseButtonEventArgs>((e)=> { 
       if (e.LeftButton == MouseButtonState.Pressed) 
       { 
        //call this function from your utils/models 
        var row = FindTemplatedParentByVisualParent<DataGridRow>((FrameworkElement)e.OriginalSource,typeof(ICommandSource)); 
        //add ICommanSource to parameters. (if actual cell contains button instead of data.) Its optional. 
        if(row!=null) 
        { 
         row.IsSelected = !row.IsSelected; 
         e.Handled = true; 
        } 
       }     
      }); 
     } 
    } 

Cuối cùng thực hiện một phương pháp (ở đâu đó trong Model) để tìm hàng (s).

public static T FindTemplatedParentByVisualParent<T>(FrameworkElement element,Type exceptionType = null) where T : class 
    { 
     if (element != null && (exceptionType == null || element.TemplatedParent == null || (exceptionType != null && element.TemplatedParent !=null && !exceptionType.IsAssignableFrom(element.TemplatedParent.GetType())))) 
     { 
      Type type = typeof(T); 
      if (type.IsInstanceOfType(element.TemplatedParent)) 
      { 
       return (element.TemplatedParent as T); 
      } 
      else 
      { 
       return FindTemplatedParentByVisualParent<T>((FrameworkElement)VisualTreeHelper.GetParent(element)); 
      } 
     } 
     else 
      return null; 
    } 

Giải pháp này làm việc hoàn hảo vì vậy tôi hy vọng nó cũng sẽ giúp ích cho bạn.

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