Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net WPF Scrollviewer不适应内容_.net_Wpf_Image_User Interface_Zooming - Fatal编程技术网

.net WPF Scrollviewer不适应内容

.net WPF Scrollviewer不适应内容,.net,wpf,image,user-interface,zooming,.net,Wpf,Image,User Interface,Zooming,我需要在我的WPF应用程序中显示一个图像,用透明画布覆盖它,并允许用户在上面绘制。用户必须能够放大图像(放大和缩小)并在图像中“导航”,同时使用停靠在窗口底部和右侧的某种滚动条进行放大。为了启用图像缩放,我使用了第二个答案中描述的。这是我的XAML代码: <ScrollViewer x:Name="imageScroll" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" > <

我需要在我的WPF应用程序中显示一个图像,用透明画布覆盖它,并允许用户在上面绘制。用户必须能够放大图像(放大和缩小)并在图像中“导航”,同时使用停靠在窗口底部和右侧的某种滚动条进行放大。为了启用图像缩放,我使用了第二个答案中描述的。这是我的XAML代码:

<ScrollViewer x:Name="imageScroll" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"  >
  <local:ZoomBorder x:Name="backgroundZoomBorder" ClipToBounds="True" HorizontalAlignment="Center" VerticalAlignment="Center"  Width="{Binding CurrentImageWidth}" Height="{Binding CurrentImageHeight}"  >
     <Grid x:Name="gridDrawing" MouseLeftButtonDown="background_MouseLeftButtonDown" MouseMove="background_MouseMove" MouseLeftButtonUp="background_MouseLeftButtonUp">                           
       <Image  x:Name="mainImage"  Source="{Binding Path=WriteableBmp}" />
       <Canvas x:Name="canvasDrawing"  Background="Transparent" />
     </Grid>
  </local:ZoomBorder>
</ScrollViewer>

但是,如果将图像放大到最大值或缩小到最小值,scollviewer不会根据内容大小进行调整,它仍然是相同的。如果图像小于窗口区域,它应该消失,或者当图像缩放时,它的范围更大。我是否可以将ScrollViever绑定到图像的转换大小或其他内容?或者有没有更好的控件来代替ScrollViewer?
谢谢

A
ScrollViewer
将永远无法使用
ZoomBorder
控件,因为它正在使用
渲染转换。
RenderTransform
在它通过布局系统后,操作您看到的内容。因此,它的大小永远不会改变,因此,
ScrollViewer
将永远不会激活

通过将
缩放顺序
修改为使用
布局转换
,您可以使缩放(滚轮)功能工作,并且
滚动查看器
将激活。然而,使用鼠标进行平移需要进行更重要的修改

下面是一些有效的示例代码:

使用LayoutTransform的ZoomOrder

using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace SO
{
    public class ZoomBorder : Border
    {
        private FrameworkElement child;

        private ScaleTransform GetScaleTransform(FrameworkElement element)
        {
            return (ScaleTransform)((TransformGroup)element.LayoutTransform)
              .Children.First(tr => tr is ScaleTransform);
        }

        public override UIElement Child
        {
            get => base.Child;
            set
            {
                if (value != null && value != Child)
                    Initialize(value);
                base.Child = value;
            }
        }

        public void Initialize(UIElement element)
        {
            child = (FrameworkElement)element;

            if (child == null) return;

            var group = new TransformGroup();
            var st = new ScaleTransform();

            @group.Children.Add(st);

            child.LayoutTransform = @group;
            child.RenderTransformOrigin = new Point(0.0, 0.0);

            MouseWheel += child_MouseWheel;
            PreviewMouseRightButtonDown += child_PreviewMouseRightButtonDown;
        }

        public void Reset()
        {
            if (child == null) return;

            // reset zoom
            var st = GetScaleTransform(child);
            st.ScaleX = 1.0;
            st.ScaleY = 1.0;
        }

        #region Child Events
        private void child_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (child != null)
            {
                var st = GetScaleTransform(child);

                var zoom = e.Delta > 0 ? .2 : -.2;

                if (!(e.Delta > 0) && (st.ScaleX < .4 || st.ScaleY < .4)) return;

                st.ScaleX += zoom;
                st.ScaleY += zoom;
            }
        }

        void child_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            Reset();
        }
        #endregion
    }
}
使用System.Linq;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
使用System.Windows.Media;
名称空间SO
{
公共类变形虫:Border
{
私有框架元素子元素;
私有ScaleTransform GetScaleTransform(FrameworkElement元素)
{
return(ScaleTransform)((TransformGroup)元素.LayoutTransform)
.Children.First(tr=>tr是ScaleTransform);
}
公共覆盖元素子元素
{
get=>base.Child;
设置
{
if(value!=null&&value!=Child)
初始化(值);
base.Child=值;
}
}
公共void初始化(UIElement)
{
子元素=(FrameworkElement)元素;
if(child==null)返回;
var group=新的TransformGroup();
var st=新的ScaleTransform();
@组。儿童。添加(st);
child.LayoutTransform=@group;
child.renderTransferMorigin=新点(0.0,0.0);
鼠标滚轮+=子鼠标滚轮;
PreviewMouseRightButtonDown+=子项\u PreviewMouseRightButtonDown;
}
公共无效重置()
{
if(child==null)返回;
//重置缩放
var st=GetScaleTransform(子级);
st.ScaleX=1.0;
st.ScaleY=1.0;
}
#地区儿童活动
私有无效子对象\鼠标滚轮(对象发送方,鼠标滚轮事件参数e)
{
if(child!=null)
{
var st=GetScaleTransform(子级);
var zoom=e.δ>0?.2:-.2;
如果(!(e.Delta>0)和(st.ScaleX<.4 | | st.ScaleY<.4))返回;
st.ScaleX+=缩放;
st.ScaleY+=缩放;
}
}
void child_PreviewMouseRightButtonDown(对象发送器,鼠标按钮ventargs e)
{
重置();
}
#端区
}
}
ScrollViewerPanBehavior 通过使用鼠标拖动来处理平移的行为

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace SO
{
    public class ScrollViewerPanBehavior : Behavior<ScrollViewer>
    {
        private UIElement content;
        private Point scrollMousePoint;
        private double scrollHorizontalOffset;
        private double scrollVerticalOffset;

        public ScrollViewerPanBehavior()
        {
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.Loaded += OnLoaded;
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            content = (UIElement)AssociatedObject.Content;
            content.MouseLeftButtonDown += OnMouseLeftButtonDown;
            content.MouseMove += OnMouseMove;
            content.MouseLeftButtonUp += OnMouseLeftButtonUp;
        }

        private void OnMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            content.CaptureMouse();
            AssociatedObject.Cursor = Cursors.Hand;
            scrollMousePoint = e.GetPosition(AssociatedObject);
            scrollHorizontalOffset = AssociatedObject.HorizontalOffset;
            scrollVerticalOffset = AssociatedObject.VerticalOffset;
        }

        private void OnMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (content.IsMouseCaptured)
            {
                var newVerticalOffset = scrollVerticalOffset + (scrollMousePoint.Y - e.GetPosition(AssociatedObject).Y);
                var newHorizontalOffset = scrollHorizontalOffset + (scrollMousePoint.X - e.GetPosition(AssociatedObject).X);

                AssociatedObject.ScrollToVerticalOffset(newVerticalOffset);
                AssociatedObject.ScrollToHorizontalOffset(newHorizontalOffset);
            }
        }

        private void OnMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            content.ReleaseMouseCapture();
            AssociatedObject.Cursor = Cursors.Arrow;
        }
    }
}
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
使用System.Windows.Interactive;
名称空间SO
{
公共类ScrollViewerPanBehavior:行为
{
私有元素内容;
专用点滚动鼠标点;
私人双滚动水平偏移;
专用双滚动垂直偏移;
公共ScrollViewerPanBehavior()
{
}
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.Loaded+=已加载;
}
已加载专用void(对象发送方,RoutedEventArgs e)
{
content=(UIElement)AssociatedObject.content;
content.MouseLeftButtonDown+=OnMouseLeftButtonDown;
content.MouseMove+=OnMouseMove;
content.MouseLeftButtonUp+=OnMouseLeftButtonUp;
}
MouseLeftButtonDown上的私有void(对象发送方,System.Windows.Input.MouseButtonEventArgs e)
{
content.CaptureMouse();
AssociatedObject.Cursor=Cursors.Hand;
scrollMousePoint=e.GetPosition(关联对象);
scrollHorizontalOffset=AssociatedObject.HorizontalOffset;
scrollVerticalOffset=AssociatedObject.VerticalOffset;
}
MouseMove上的私有void(对象发送方,System.Windows.Input.MouseEventArgs e)
{
if(content.ismouseCapture)
{
var newVerticalOffset=scrollVerticalOffset+(scrollMousePoint.Y-e.GetPosition(AssociatedObject.Y);
var newHorizontalOffset=scrollHorizontalOffset+(scrollMousePoint.X-e.GetPosition(AssociatedObject.X);
AssociatedObject.ScrollToVerticalOffset(新建VerticalOffset);
AssociatedObject.ScrollToHorizontalOffset(新建HorizontalOffset);
}
}
MouseLeftButtonUp上的私有void(对象发送方,System.Windows.Input.MouseButtonEventArgs e)
{
content.ReleaseMouseCapture();
AssociatedObject.Cursor=Cursors.Arrow;
}
}
}
用法示例:

<ScrollViewer
    HorizontalScrollBarVisibility="Auto"
    VerticalScrollBarVisibility="Auto">
    <i:Interaction.Behaviors>
        <local:ScrollViewerPanBehavior />
    </i:Interaction.Behaviors>
    <local:ZoomBorder
        HorizontalAlignment="Center"
        VerticalAlignment="Center">
        <Grid>
            <Image Source="ThumbsUp.png" />
        </Grid>
    </local:ZoomBorder>
</ScrollViewer>

这很有趣