我正在尝试创建一个自定义面板,允许用户根据需要排列控件。这似乎工作,我不能让垂直滚动工作。我已经尝试使用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;
}
}