2

データグリッド内で WindowsFormsHost を使用しているときに、コントロールがグリッドのスクロール可能な領域をオーバーランします。

ここに記載されているソリューションを使用してみましたが、ScrollViewer は WPF WindowsFormHost で動作しません

ScrollableWindowsFormsHost クラスを使用して、コントロールをスクロール領域に制限することもできます。ただし、セル内を 2 回クリックしない限り、Winforms コントロール (Winforms コンボ ボックスから派生したコントロール) は表示されません (最初にセルにフォーカスをクリックし、2 回目のクリックでコンボボックスを描画します)。これは、ウィンドウの再描画時に再び消えます。 .

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

1 に答える 1

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);
        }
    }
}
于 2013-03-18T15:41:55.133 に答える