2013-03-14 5 views
1

При использовании WindowsFormsHost внутри datagrid мои элементы управления переполняют прокручиваемую область сетки.Использование WindowsFormsHost внутри datagrid, область прокрутки переполнения

Я пробовал использовать упомянутые здесь решения, ScrollViewer is not working in WPF WindowsFormHost.

Я также могу ограничить элементы управления областью прокрутки, используя класс ScrollableWindowsFormsHost. Тем не менее, мой контроль Winforms (который является элементом управления, полученным из комбинированного поля Winforms), не будет отображаться, если я не дважды щелкнул внутри ячейки (сначала нажмите на ячейку, второй щелчок начертит мой combobox), который снова исчезает при перерисовании окна ,

из XAML:

  <toolkit:DataGridTemplateColumn> 
       <toolkit:DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <controls:HostedWinformsCombobox> 
         </controls:HostedWinformsCombobox> 
        </DataTemplate> 
       </toolkit:DataGridTemplateColumn.CellTemplate> 
      </toolkit:DataGridTemplateColumn> 

код из ScrollableWindowsFormsHost.

//-------------------------------------------------------------------------------- 
    /// <summary>Scroll handler manages the clipping of this windows forms host.</summary> 
    /// <param name="sender">Sender</param> 
    /// <param name="ea">Event argument</param> 
    private void ScrollHandler(Object sender, ScrollChangedEventArgs ea) 
    { 
     PresentationSource presentationSource = HwndSource.FromVisual(this); 
     if (presentationSource == null) 
     { 
      return; 
     } 
     Visual rootVisual = presentationSource.RootVisual; 
     if (rootVisual == null) 
     { 
      return; 
     } 
     ScrollViewer scrollViewer = (ScrollViewer)sender; 
     if (!scrollViewer.IsDescendantOf(rootVisual)) 
     { 
      return; 
     } 

     // calculate the rect of scrollview with 0/0 at upper left corner of root visual 
     GeneralTransform transform = scrollViewer.TransformToAncestor(rootVisual); 
     Rect scrollRect = transform.TransformBounds(new Rect(0, 0, scrollViewer.ViewportWidth, scrollViewer.ViewportHeight)); 

     // calculate the rect of the scrollable windows forms host instance with 0/0 at upper left corner of root visual 
     transform = this.TransformToAncestor(rootVisual); 
     Rect hostRect = transform.TransformBounds(new Rect(this.Padding.Left, this.Padding.Right, 
      this.RenderSize.Width, this.RenderSize.Height)); 

     // calculate the intersection of the two rect 
     Rect intersectRect = Rect.Intersect(scrollRect, hostRect); 

     Int32 topLeftX = 0; 
     Int32 topLeftY = 0; 
     Int32 bottomRightX = 0; 
     Int32 bottomRightY = 0; 
     if (intersectRect != Rect.Empty) 
     { 
      // calculate the HRGN points with 0/0 at upper left corner of scrollable windows forms host instance 
      //topLeftX = (Int32)(intersectRect.TopLeft.X - hostRect.TopLeft.X); 
      //topLeftY = (Int32)(intersectRect.TopLeft.Y - hostRect.TopLeft.Y); 
      //bottomRightX = (Int32)(intersectRect.BottomRight.X - hostRect.TopLeft.X); 
      //bottomRightY = (Int32)(intersectRect.BottomRight.Y - hostRect.TopLeft.Y); 

      //modified from original function - this one draws it correctly without     drawing over the title bar etc. 
      topLeftX = (Int32)(intersectRect.TopLeft.X); 
      topLeftY = (Int32)(intersectRect.TopLeft.Y); 
      bottomRightX = (Int32)(intersectRect.BottomRight.X); 
      bottomRightY = (Int32)(intersectRect.BottomRight.Y); 
     } 

     // because the CreateRectRgn/SetWindowRgn api calls are slow we call them only if it has a visual effect 
     if (_topLeftX != topLeftX || _topLeftY != topLeftY || _bottomRightX != bottomRightX || _bottomRightY != bottomRightY) 
     { 
      _topLeftX = topLeftX; 
      _topLeftY = topLeftY; 
      _bottomRightX = bottomRightX; 
      _bottomRightY = bottomRightY; 
      // create HRGN object and set it to the windows forms host instance 
      IntPtr hrgn = CreateRectRgn(_topLeftX, _topLeftY, _bottomRightX, _bottomRightY); 
      SetWindowRgn(this.Handle, hrgn, true); 

      // I tried the following to fix the issue, but neither ones worked 
      this.UpdateLayout(); //doesn't work 

      this.Child.Show();  //doesn't work 
     } 
    } 
+0

Вы пытались настроить режим AutoScale на своих элементах управления WinForms на Dpi? – Brannon

ответ

1

Эта часть кода работала для меня.

public class DataGridWindowsFormsHost : WindowsFormsHost 
{ 
    private Int32 _topLeftX = -1; 
    private Int32 _topLeftY = -1; 
    private Int32 _bottomRightX = -1; 
    private Int32 _bottomRightY = -1; 

    private const int _titleBarHeight = 25; // must leave the space for the title bar in DataGrid 
    private const int _scrollbarHeight = 5; // must leave space for horizontal scroll area in the bottom 

    //-------------------------------------------------------------------------------- 
    /// <summary>Creates a DataGridWindowsFormsHost.</summary> 
    public DataGridWindowsFormsHost() 
    { 
     // Register the event handler 
     EventManager.RegisterClassHandler(typeof(ScrollViewer), ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(ScrollHandler)); 
    } 

    [DllImport("GDI32.DLL", EntryPoint = "CreateRectRgn")] 
    private static extern IntPtr CreateRectRgn(Int32 x1, Int32 y1, Int32 x2, Int32 y2); 
    [DllImport("User32.dll", SetLastError = true)] 
    private static extern Int32 SetWindowRgn(IntPtr hWnd, IntPtr hRgn, Boolean bRedraw); 


    private DataGrid _dGrid; 
    public DataGrid DGrid 
    { 
     get 
     { 
      if(_dGrid == null) 
      { 
       PresentationSource presentationSource = HwndSource.FromVisual(this); 
       Visual rootVisual = presentationSource.RootVisual; 
       _dGrid = VisualTreeHelperExt.FindChildByName<DataGrid>(_rootVisual, "myDataGrid") as DataGrid; 
      } 

      return _dGrid; 
     } 
    } 

    //-------------------------------------------------------------------------------- 
    /// <summary>Scroll handler manages the clipping of this windows forms host.</summary> 
    /// <param name="sender">Sender</param> 
    /// <param name="ea">Event argument</param> 
    private void ScrollHandler(Object sender, ScrollChangedEventArgs ea) 
    { 
     PresentationSource presentationSource = HwndSource.FromVisual(this); 
     Visual rootVisual = presentationSource.RootVisual; 

     GeneralTransform transform = DGrid.TransformToAncestor(rootVisual); 
     // leave the space for title bar and horizontal scrollbar at the bottom 
     Rect gridRect = transform.TransformBounds(new Rect(0, _titleBarHeight, 
      DGrid.ActualWidth - _scrollbarHeight, DGrid.ActualHeight - _titleBarHeight)); 

     transform = this.TransformToAncestor(_rootVisual); 
     // find the rect of the hosting control 
     Rect hostRect = transform.TransformBounds(new Rect(this.Padding.Left, this.Padding.Right, 
      this.RenderSize.Width, this.RenderSize.Height)); 

     var intersectRect = Rect.Intersect(gridRect, hostRect); 
     Int32 topLeftX = 0; 
     Int32 topLeftY = 0; 
     Int32 bottomRightX = 0; 
     Int32 bottomRightY = 0; 
     if (intersectRect != Rect.Empty) 
     { 
      // calculate the HRGN points with 0/0 at upper left corner of scrollable windows forms host instance 
      topLeftX = (Int32)(intersectRect.TopLeft.X - hostRect.TopLeft.X); 
      topLeftY = (Int32)(intersectRect.TopLeft.Y - hostRect.TopLeft.Y); 
      bottomRightX = (Int32)(intersectRect.BottomRight.X - hostRect.TopLeft.X); 
      bottomRightY = (Int32)(intersectRect.BottomRight.Y - hostRect.TopLeft.Y); 
     } 

     // because the CreateRectRgn/SetWindowRgn api calls are slow we call them only if it has a visual effect 
     if (_topLeftX != topLeftX || _topLeftY != topLeftY || _bottomRightX != bottomRightX || _bottomRightY != bottomRightY) 
     { 
      _topLeftX = topLeftX; 
      _topLeftY = topLeftY; 
      _bottomRightX = bottomRightX; 
      _bottomRightY = bottomRightY; 

      // create HRGN object and set it to the windows forms host instance 
      IntPtr hrgn = CreateRectRgn(_topLeftX, _topLeftY, _bottomRightX, _bottomRightY); 
      SetWindowRgn(this.Handle, hrgn, true); 
     } 
    } 
}