自定义面板不垂直滚动

时间:2018-06-18 15:27:25

标签: wpf wpf-controls

我正在尝试创建一个自定义面板,允许用户根据需要排列控件。这似乎工作,我不能让垂直滚动工作。我已经尝试使用scrollviewer等设置我的面板的高度。水平滚动就像一个魅力。

你可以帮我弄清楚我错过了什么。我想知道这是一个模板问题还是某种类似问题。 SignalLayoutPanel是我想要滚动的面板。

主窗口xaml:

<dock:DockingManager x:Name="Dock1" Grid.Row="1" 
                     AllowMixedOrientation="True"
                         DocumentsSource="{Binding Path=VisibleDockWindows}"
                         AnchorablesSource="{Binding Path=Tools}"
                         ActiveContent="{Binding ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}"

                     >
        <dock:DockingManager.Theme>
            <dock:AeroTheme/>
        </dock:DockingManager.Theme>
        <dock:DockingManager.LayoutItemTemplateSelector><!--Section determines which View is used-->
            <pane:PanesTemplateSelector>
                <pane:PanesTemplateSelector.FileViewTemplate>
                    <DataTemplate>
                        <local:SignalWindow AllowDrop="True" Background="LightGray" Height="Auto"/> <!--Panel not scrolling-->
                    </DataTemplate>
                </pane:PanesTemplateSelector.FileViewTemplate>
                <pane:PanesTemplateSelector.SignalExplorerViewTemplate>
                    <DataTemplate>
                        <local:SignalExplorerTree/>
                    </DataTemplate>
                </pane:PanesTemplateSelector.SignalExplorerViewTemplate>
                <pane:PanesTemplateSelector.PanelExplorerViewTemplate>
                    <DataTemplate>
                        <local:PanelExplorerWindow/>
                    </DataTemplate>
                </pane:PanesTemplateSelector.PanelExplorerViewTemplate>
                <pane:PanesTemplateSelector.PropertiesViewTemplate>
                    <DataTemplate>
                        <local:PropertyViewer1/>
                    </DataTemplate>
                </pane:PanesTemplateSelector.PropertiesViewTemplate>
            </pane:PanesTemplateSelector>
        </dock:DockingManager.LayoutItemTemplateSelector>
        <dock:DockingManager.LayoutItemContainerStyleSelector>
            <pane:PanesStyleSelector>
                <pane:PanesStyleSelector.ToolStyle>
                    <Style TargetType="{x:Type dock:LayoutAnchorableItem}">
                        <Setter Property="Title" Value="{Binding Model.Title}"/>
                        <Setter Property="Visibility" Value="{Binding Model.IsVisible, ConverterParameter={x:Static Visibility.Hidden}, Converter={StaticResource btvc}, Mode=TwoWay}"/>
                        <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
                        <Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/>
                        <Setter Property="ContentId" Value="{Binding Model.ContentID}"/>
                    </Style>
                </pane:PanesStyleSelector.ToolStyle>
                <pane:PanesStyleSelector.FileStyle>
                    <Style TargetType="{x:Type dock:LayoutItem}">
                        <Setter Property="Title" Value="{Binding Model.Title}"/>
                        <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
                        <Setter Property="ContentId" Value="{Binding Model.ContentID}"/>
                    </Style>
                </pane:PanesStyleSelector.FileStyle>
            </pane:PanesStyleSelector>
        </dock:DockingManager.LayoutItemContainerStyleSelector>
</dock:DockingManager>

SignalWindow.xaml:

<UserControl x:Class="ControllerInterfaceWithExplorer2.SignalWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:ControllerInterfaceWithExplorer2"
         xmlns:lv ="clr-namespace:ControllerInterfaceWithExplorer2.View"
         xmlns:VM="clr-namespace:ControllerInterfaceWithExplorer2.ViewModel"
         mc:Ignorable="d" 
         d:DesignHeight="100" d:DesignWidth="100"
         AllowDrop="True">
<UserControl.Resources>
    <VM:SignalTemplateSelector x:Key="myDataTemplateSelector"/>
    <DataTemplate x:Key="DID">
        <local:SignalViewer/>
    </DataTemplate>
    <DataTemplate x:Key="RID">
        <local:RoutineViewer/>
    </DataTemplate>
    <DataTemplate x:Key="IO">
        <local:IOViewer/>
    </DataTemplate>
</UserControl.Resources>
<Grid Height="Auto" Width="Auto">
    <Grid.RowDefinitions>
        <RowDefinition Height="80"/>
        <RowDefinition Height="20"/>
    </Grid.RowDefinitions>
    <ScrollViewer HorizontalScrollBarVisibility="Auto" 
                  VerticalScrollBarVisibility="Auto"
                  Grid.Row="0" Height="80">
        <ItemsControl Grid.Row="0" ItemsSource="{Binding Signals}"  
                  ItemTemplateSelector="{StaticResource myDataTemplateSelector}">

            <ItemsControl.ItemsPanel >

                <ItemsPanelTemplate>
                    <!--Panel that won't scroll vertically-->
                    <lv:SignalLayoutPanel Height="Auto" AllowDrop="True" />

                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>


        </ItemsControl>
    </ScrollViewer>

    <!--<StackPanel Grid.Row="1" Orientation="Horizontal">
        <Button Content="Read" Click="Button_Click"/>
        <Button Content="Write" Click="Button_Click_1"/>
    </StackPanel>-->
    <!--<DockPanel x:Name="dockPanel" MouseDown="dockPanel_MouseDown" MouseMove="dockPanel_MouseMove" MouseUp="dockPanel_MouseUp">
        <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
            <Button Content="Read" Click="Button_Click"/>
            <Button Content="Write" Click="Button_Click_1"/>
        </StackPanel>
        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True" Height="150" Width="Auto">
        <ItemsControl DockPanel.Dock="Top" ItemsSource="{Binding Signals}"  
                  ItemTemplateSelector="{StaticResource myDataTemplateSelector}" MouseDown="dockPanel_MouseDown">

                <ItemsControl.ItemsPanel >
                    <ItemsPanelTemplate>
                        <lv:SignalLayoutPanel AllowDrop="True" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

        </ItemsControl>
        </ScrollViewer>
    </DockPanel>-->


</Grid>

SignalLayoutPanel.cs:

 public class SignalLayoutPanel:Panel
{
    public SignalLayoutPanel()
    {
        this.Background = Brushes.Chartreuse;
        this.MouseMove += SignalLayoutPanel_MouseMove;
        this.MouseEnter += SignalLayoutPanel_MouseEnter;
        this.MouseLeave += SignalLayoutPanel_MouseLeave;
        this.DragEnter += SignalLayoutPanel_DragEnter;
        this.MouseDown += SignalLayoutPanel_MouseDown;
        this.MouseUp += SignalLayoutPanel_MouseUp;
        this.Drop += SignalLayoutPanel_Drop;
        this.SourceUpdated += SignalLayoutPanel_SourceUpdated;
        this.TargetUpdated += SignalLayoutPanel_TargetUpdated;

    }


    private void SignalLayoutPanel_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        _currentControl = null;
        InvalidateArrange();
    }

    private StackPanel _currentControl;

    private void SignalLayoutPanel_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        var result = VisualTreeHelper.HitTest(this, e.GetPosition(this));
        _currentControl = GetCurrentStackPanel(result);
    }

    private void SignalLayoutPanel_TargetUpdated(object sender, System.Windows.Data.DataTransferEventArgs e)
    {
    }

    private void SignalLayoutPanel_SourceUpdated(object sender, System.Windows.Data.DataTransferEventArgs e)
    {
    }

    private void SignalLayoutPanel_Drop(object sender, DragEventArgs e)
    {
        var data = e.Data.GetData(typeof(ViewModel.SignalViewModel));
        if (data != null)
        {
            ViewModel.SignalViewModel vm = data as ViewModel.SignalViewModel;
            ViewModel.SignalWindowViewModel svw = this.DataContext as ViewModel.SignalWindowViewModel;
            if (vm.Model.GetType() == typeof(DataModel.DIDClass))
            {
                double tempX = e.GetPosition(this).X;
                double tempY = e.GetPosition(this).Y;
                foreach (ViewModel.SignalViewModel signalView in vm.Children)
                {
                    signalView.PositionX = tempX;
                    signalView.PositionY = tempY;
                    //Signals.Add(signalView);
                    svw.Add(signalView);
                    tempY += 40;
                }
            }
            else
            {
                vm.PositionX = e.GetPosition(this).X;
                vm.PositionY = e.GetPosition(this).Y;


                svw.Add(vm);
            }


        }

    }

    private void SignalLayoutPanel_DragEnter(object sender, DragEventArgs e)
    {
        e.Effects = DragDropEffects.None;
        var data = e.Data.GetData(typeof(ViewModel.SignalViewModel));
        //get signal
        if (data != null)
        {
            e.Effects = DragDropEffects.All;
        }
        else
        {

        }
    }

    private void SignalLayoutPanel_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
    {

    }

    private void SignalLayoutPanel_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
    {

    }

    private void SignalLayoutPanel_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
    {
        if(e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && _currentControl != null)
        {
            if(_currentControl.DataContext is ViewModel.SignalViewModel)
            {
                ViewModel.SignalViewModel svm = _currentControl.DataContext as ViewModel.SignalViewModel;
                svm.PositionX = e.GetPosition(this).X;
                svm.PositionY = e.GetPosition(this).Y;
            }
        }
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        Size idealSize = new Size(0, 0);

        // Allow children as much room as they want - then scale them
        Size size = new Size(Double.PositiveInfinity, Double.PositiveInfinity);
        foreach (UIElement child in Children)
        {
            child.Measure(size);
            idealSize.Width += child.DesiredSize.Width;
            idealSize.Height = 20;// Math.Max(idealSize.Height, child.DesiredSize.Height);
        }

        // EID calls us with infinity, but framework doesn't like us to return infinity
        if (double.IsInfinity(availableSize.Height) || double.IsInfinity(availableSize.Width))
            return idealSize;
        else
            return availableSize;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        //double x = 5;
        //double y = 5;

        //for(int i=0; i < InternalChildren.Count; i++)
        //{
        //    InternalChildren[i].Arrange(new Rect(new Point(x, y), InternalChildren[i].DesiredSize));
        //    y += InternalChildren[i].DesiredSize.Height;


        //}
        foreach(UIElement child in InternalChildren)
        {
           if( ((System.Windows.FrameworkElement)child).DataContext  is ViewModel.SignalViewModel)
            {
                ViewModel.SignalViewModel svm = ((System.Windows.FrameworkElement)child).DataContext as ViewModel.SignalViewModel;
                child.Arrange(new Rect(new Point(svm.PositionX, svm.PositionY), child.DesiredSize));
            }
        }

        return finalSize;
    }

    private StackPanel GetCurrentStackPanel(HitTestResult hitTest)
    {
        StackPanel retVal = null;
        var element = hitTest.VisualHit as FrameworkElement;
        FrameworkElement temp = element;
        while (temp != null && !(temp is StackPanel))
            if (temp != null)
                temp = temp.Parent as FrameworkElement;
        if (temp != null)
            retVal = temp as StackPanel;
        return retVal;
    }
}

0 个答案:

没有答案