WPF GridSplitter visiblity

廉价感情. 提交于 2019-12-10 11:54:37

问题


I have a problem regarding GridSplitter visiblity.

In this, whatever I am hosting a Winform DataGridView. The GridSplitter, when dragged is properly visible on other controls. But not on this grid. In fact, whatever I host instead of Datagridview, becomes the topmost control, which makes the GridSplitter hide behind it.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Name="rowForButton"/>
        <RowDefinition Name="rowForGridSplitter" Height="Auto" MinHeight="81" />
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Height="50" Width="110" Content="Button in First Row"/>
    <my:WindowsFormsHost Panel.ZIndex="0" Grid.Row="1"  Margin="30,11,138,0" x:Name="winHost" Height="58" VerticalAlignment="Top" OpacityMask="Transparent">            
        <win:DataGridView x:Name="dataGridView"></win:DataGridView>
    </my:WindowsFormsHost>        
    <GridSplitter  BorderThickness="1" Panel.ZIndex="1" Grid.Row="1" HorizontalAlignment="Stretch" Height="5" ShowsPreview="True" VerticalAlignment="Top">
    </GridSplitter>
</Grid>

回答1:


Windows Forms controls are always rendered seperately from your WPF controls, and as a result will always appear over your WPF application.

See Hosting a Microsoft Win32 Window in WPF (subheading Notable Differences in Output Behavior) for more info.




回答2:


Usually you should either put a GridSplitter into its own grid cell or ensure via margins that no control can overlap it. But I don't know whether that exactly applies to you here. See also here.




回答3:


I encountered this problem also, there is my solution:

var splitter = new GridSplitter()
        {
            HorizontalAlignment = HorizontalAlignment.Stretch,
            VerticalAlignment = VerticalAlignment.Stretch,
            FocusVisualStyle = null,
            ShowsPreview = true,
            Background = new SolidColorBrush(new Color() { R = 1, G = 1, B = 1, A = 1 }),
        };

// non-style / essential window which will display over your WinForm control
var PopupWindowForSplitter = new PopupWindow()
        {
            Background = new SolidColorBrush(new Color() { R = 1, G = 1, B = 1, A = 1 }),
            Visibility = Visibility.Collapsed
        };
PopupWindowForSplitter.Show();
...

Point _ptForSplitterDrag = new Point(0,0);

splitter.DragStarted += (o, e) =>
        {
            var pt = splitter.PointToScreen(new Point());
            _ptForSplitterDrag = splitter.PointToScreen(Mouse.GetPosition(splitter));
            PopupWindowForSplitter.Left = pt.X;
            PopupWindowForSplitter.Top = pt.Y;
            PopupWindowForSplitter.Height = splitter.ActualHeight;
            PopupWindowForSplitter.Width = splitter.ActualWidth;
            PopupWindowForSplitter.Activate();
            PopupWindowForSplitter.Visibility = Visibility.Visible;
        };
        splitter.DragDelta += (o, e) =>
        {
            var pt = splitter.PointToScreen(Mouse.GetPosition(splitter)) - _ptForSplitterDrag
                + splitter.PointToScreen(new Point());
            if (splitter.ResizeDirection == GridResizeDirection.Rows)
            {
                PopupWindowForSplitter.Top = pt.Y;
            }
            else
            {
                PopupWindowForSplitter.Left = pt.X;
            }
        };
        splitter.DragCompleted += (o, e) =>
        {
            var initializeData = typeof(GridSplitter).GetMethod("InitializeData", BindingFlags.NonPublic | BindingFlags.Instance);
            var moveSplitter = typeof(GridSplitter).GetMethod("MoveSplitter", BindingFlags.NonPublic | BindingFlags.Instance);
            if (moveSplitter != null && initializeData != null)
            {
                initializeData.Invoke(splitter, new object[] { true });

                var pt = splitter.PointToScreen(Mouse.GetPosition(splitter)) - _ptForSplitterDrag;
                if (splitter.ResizeDirection == GridResizeDirection.Rows)
                {
                    moveSplitter.Invoke(splitter, new object[] { 0, pt.Y });
                }
                else
                {
                    moveSplitter.Invoke(splitter, new object[] { pt.X, 0 });
                }
            }
            PopupWindowForSplitter.Visibility = Visibility.Collapsed;
        };

Maybe there are some issues in my description because of my poor english, but I think the code is enough to explain it.




回答4:


Try using a WPF-native DataGrid control. There are a couple of commercial third-party controls you can buy, or you could take a look at one provided by Microsoft (currently still in CTP):

  • Xceed DataGrid
  • Telerik RadGridView
  • Microsoft DataGrid CTP



回答5:


In your situation, the quickest fix would be to move the GirdSplitter to the Row with the Button:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Name="rowForButton"/>
        <RowDefinition Name="rowForGridSplitter" Height="Auto" MinHeight="81" />
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Height="50" Width="110" Content="Button in First Row"/>
    <my:WindowsFormsHost Panel.ZIndex="0" Grid.Row="1"  Margin="30,11,138,0" x:Name="winHost" Height="58" VerticalAlignment="Top" OpacityMask="Transparent">            
        <win:DataGridView x:Name="dataGridView"></win:DataGridView>
    </my:WindowsFormsHost>        
    <GridSplitter  BorderThickness="1" Panel.ZIndex="1" Grid.Row="0" HorizontalAlignment="Stretch" Height="5" ShowsPreview="True" VerticalAlignment="Bottom">
    </GridSplitter>
</Grid>

Now just adjust the margins to make sure there is some space between the button and the grid splitter.




回答6:


The solution would be to add a 'Windows Form' label inside the grid splitter, and to do so programmatically after the addition of the DataGridView so it appears on top of it, as follows:

void AddLabelToSplitter()
{
string template =
    @" <ControlTemplate 
xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:mn='clr-namespace:MyNameSpace;assembly=MyAssembly'  
xmlns:wf='clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms'   
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' TargetType='{x:Type GridSplitter}'>
            <mn:ExtendedWindowsFormsHost x:Name='Grid_Splitter_WindowsFormsHost' HorizontalAlignment='Stretch'  VerticalAlignment='Stretch'>
                <wf:Label Dock='Fill' BackColor='DarkGray'></wf:Label>
            </mn:ExtendedWindowsFormsHost>
        </ControlTemplate>";
Grid_Splitter.Template = (ControlTemplate)XamlReader.Parse(template);
}

Using a regular windows form host would not work, as it wouldn't pass down the mouse events to the splitter, so use the ExtendedWindowsFormsHost instead from below link:

Keep Mouse Events bubbling from WindowsFormsHost on



来源:https://stackoverflow.com/questions/720375/wpf-gridsplitter-visiblity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!