ItemsControl 中的多个 InkCanvas 实例 -> 其他实例上的 MousePress 导致长行
Multiple InkCanvas instances in ItemsControl -> MousePress on other instance results in long line
我在 ItemsControl 中使用多个 InkCanvas 实例时遇到问题。每个 InkCanvas 实例都接收一个 ImageBrush 作为背景,然后添加到 ItemsControl。基本上这是一个自己编写的 PdfViewer,用户可以在 PdfPages 上绘制评论等,然后再次将文件另存为 pdf。读取原始 pdf,将页面转换为位图,并将每个位图用作 InkCanvas 的背景。
只要我不点击另一个 canvas,它就可以正常工作。这里有两张图片来说明问题:
XAML 的 PdfViewer:
<UserControl x:Class="PdfTool.Code.Controls.PdfViewer"
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:viewModel="clr-namespace:PdfTool.Code.ViewModel"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance {x:Type viewModel:CanvasViewModel}, IsDesignTimeCreatable=False}"
d:DesignHeight="450" d:DesignWidth="800">
<ScrollViewer PanningMode="Both" Background="{StaticResource MainBackgroundColor}">
<ItemsControl x:Name="PagesContainer" MouseWheel="PagesContainer_OnMouseWheel">
<ItemsControl.RenderTransform>
<MatrixTransform/>
</ItemsControl.RenderTransform>
</ItemsControl>
</ScrollViewer>
</UserControl>
后面的代码:
public partial class PdfViewer : UserControl
{
#region Bindable Properties
...
#endregion
public PdfViewer()
{
InitializeComponent();
}
private static async Task PdfToImages(PdfViewer pdfViewer, PdfDocument pdfDoc)
{
pdfViewer.Dispatcher.Invoke(() => pdfViewer.PagesContainer.Items.Clear());
if (pdfDoc == null) return;
for (uint i = 0; i < pdfDoc.PageCount; i++) {
using (var page = pdfDoc.GetPage(i)) {
await pdfViewer.Dispatcher.Invoke(async () =>
{
var bitmap = await PageToBitmapAsync(page);
pdfViewer.PagesContainer.Items.Add(new PdfDetailElement(new ImageBrush(bitmap) {Stretch = Stretch.Uniform}));
});
}
}
}
...
}
单个 PdfPage 的 XAML:
<UserControl x:Class="PdfTool.Code.Controls.PdfDetailElement"
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:viewModel="clr-namespace:PdfTool.Code.ViewModel"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance {x:Type viewModel:CanvasViewModel}, IsDesignTimeCreatable=False}"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Margin="10,10,5,10">
<Viewbox Stretch="Fill">
<InkCanvas x:Name="inkCanvas"
Background="{x:Null}"
DefaultDrawingAttributes="{Binding SelectedDrawingAttributes}"
EditingMode="{Binding SelectedEditingMode, UpdateSourceTrigger=PropertyChanged}"/>
</Viewbox>
</Grid>
</UserControl>
后面的代码:
public partial class PdfDetailElement : UserControl
{
public PdfDetailElement()
{
InitializeComponent();
}
public PdfDetailElement(ImageBrush image)
{
DataContext = Gui.Main.CanvasSettings;
InitializeComponent();
inkCanvas.Background = image;
inkCanvas.Width = image.ImageSource.Width;
inkCanvas.Height = image.ImageSource.Height;
}
}
只有 MouseWheel 事件用于缩放,这不是问题的原因。看来,鼠标在 InkCanvas 1 上的坐标用作 InkCanvas 2 的初始值。如何更改此行为?
我明白了:Stop WPF ScrollViewer automatically scrolling to perceived content 让我朝着正确的方向前进。我只需要设置
Focusable="False"
在 InkCanvas 上,我的问题已解决,因为如果要进入视图的对象不可聚焦,则不会触发滚动条的 RequestBringIntoView 事件...
我在 ItemsControl 中使用多个 InkCanvas 实例时遇到问题。每个 InkCanvas 实例都接收一个 ImageBrush 作为背景,然后添加到 ItemsControl。基本上这是一个自己编写的 PdfViewer,用户可以在 PdfPages 上绘制评论等,然后再次将文件另存为 pdf。读取原始 pdf,将页面转换为位图,并将每个位图用作 InkCanvas 的背景。
只要我不点击另一个 canvas,它就可以正常工作。这里有两张图片来说明问题:
XAML 的 PdfViewer:
<UserControl x:Class="PdfTool.Code.Controls.PdfViewer"
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:viewModel="clr-namespace:PdfTool.Code.ViewModel"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance {x:Type viewModel:CanvasViewModel}, IsDesignTimeCreatable=False}"
d:DesignHeight="450" d:DesignWidth="800">
<ScrollViewer PanningMode="Both" Background="{StaticResource MainBackgroundColor}">
<ItemsControl x:Name="PagesContainer" MouseWheel="PagesContainer_OnMouseWheel">
<ItemsControl.RenderTransform>
<MatrixTransform/>
</ItemsControl.RenderTransform>
</ItemsControl>
</ScrollViewer>
</UserControl>
后面的代码:
public partial class PdfViewer : UserControl
{
#region Bindable Properties
...
#endregion
public PdfViewer()
{
InitializeComponent();
}
private static async Task PdfToImages(PdfViewer pdfViewer, PdfDocument pdfDoc)
{
pdfViewer.Dispatcher.Invoke(() => pdfViewer.PagesContainer.Items.Clear());
if (pdfDoc == null) return;
for (uint i = 0; i < pdfDoc.PageCount; i++) {
using (var page = pdfDoc.GetPage(i)) {
await pdfViewer.Dispatcher.Invoke(async () =>
{
var bitmap = await PageToBitmapAsync(page);
pdfViewer.PagesContainer.Items.Add(new PdfDetailElement(new ImageBrush(bitmap) {Stretch = Stretch.Uniform}));
});
}
}
}
...
}
单个 PdfPage 的 XAML:
<UserControl x:Class="PdfTool.Code.Controls.PdfDetailElement"
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:viewModel="clr-namespace:PdfTool.Code.ViewModel"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance {x:Type viewModel:CanvasViewModel}, IsDesignTimeCreatable=False}"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Margin="10,10,5,10">
<Viewbox Stretch="Fill">
<InkCanvas x:Name="inkCanvas"
Background="{x:Null}"
DefaultDrawingAttributes="{Binding SelectedDrawingAttributes}"
EditingMode="{Binding SelectedEditingMode, UpdateSourceTrigger=PropertyChanged}"/>
</Viewbox>
</Grid>
</UserControl>
后面的代码:
public partial class PdfDetailElement : UserControl
{
public PdfDetailElement()
{
InitializeComponent();
}
public PdfDetailElement(ImageBrush image)
{
DataContext = Gui.Main.CanvasSettings;
InitializeComponent();
inkCanvas.Background = image;
inkCanvas.Width = image.ImageSource.Width;
inkCanvas.Height = image.ImageSource.Height;
}
}
只有 MouseWheel 事件用于缩放,这不是问题的原因。看来,鼠标在 InkCanvas 1 上的坐标用作 InkCanvas 2 的初始值。如何更改此行为?
我明白了:Stop WPF ScrollViewer automatically scrolling to perceived content 让我朝着正确的方向前进。我只需要设置
Focusable="False"
在 InkCanvas 上,我的问题已解决,因为如果要进入视图的对象不可聚焦,则不会触发滚动条的 RequestBringIntoView 事件...