【发布时间】:2016-02-17 22:56:51
【问题描述】:
我的最后一个问题被标记为重复,所以我尝试说明有什么区别。
有没有什么方法可以绑定图层并且不为每个图层创建一个 Canvas 元素?
如果没有,那么它几乎可以工作,但是: 多个画布重叠。如果我设置背景属性,下面的画布将不可见。即使背景设置为透明,鼠标事件也仅由顶部的画布获取。
如果我将 ClipToBounds 属性设置为 True(并且不设置宽度和高度),则标记不可见。宽度和高度与主画布不同。如何将这些属性绑定到主画布宽度和高度。我知道每一层都有相同的尺寸,所以我认为在每一层中存储重复信息并不好。
编辑: 我为我的误会道歉。我尽量澄清:
我想解决的问题(问题)是:
有什么方法可以绑定Layers,不为每个图层创建一个Canvas元素吗?
现在我有 mainCanvas + 多个 innerCanvases。可能只是 mainCanvas 吗?对渲染性能有影响吗?
如何设置内部 Canvas 的 Width 和 Height,使其与主 Canvas 具有相同的尺寸,而无需绑定?
mainCanvas 自动填充所有空间,但 innerCanvases 不会。 ClipToBounds=True 必须在 innerCanvases 上设置。 试过 HorizontalAligment=Stretch 但它不起作用。
重叠:好的,我想我漏掉了什么。
如果我根本不设置背景,它应该可以正常工作。对我来说很有趣的是,不设置背景与背景=透明的效果不同。**
对不起我的英语。
编辑:感谢您的回答
我认为如果我的代码不复杂化会更好,至少现在是这样。正如你所说,我发现了如何绑定到 ActualWidth:
<Canvas Width="{Binding ElementName=mainCanvas, Path=ActualWidth}"/>
或在 mainCanvas 上设置 ClipToBounds=True,而不是在内部设置。我只是希望在 mainCanvas 尺寸之外具有位置 X、Y 的标记不可见。这就是为什么我需要设置 innerCanvases 的宽度、高度。
现在一切正常,标记为答案。
这是我的代码:
ViewModel.cs
public class ViewModel
{
public ObservableCollection<LayerClass> Layers
{ get; set; }
public ViewModel()
{
Layers = new ObservableCollection<LayerClass>();
for (int j = 0; j < 10; j++)
{
var Layer = new LayerClass();
for (int i = 0; i < 10; i++)
{
Layer.Markers.Add(new MarkerClass(i * 20, 10 * j));
}
Layers.Add(Layer);
}
}
}
LayerClass.cs
public class LayerClass
{
public ObservableCollection<MarkerClass> Markers
{ get; set; }
public LayerClass()
{
Markers = new ObservableCollection<MarkerClass>();
}
}
MarkerClass.cs
public class MarkerClass
{
public int X
{ get; set; }
public int Y
{ get; set; }
public MarkerClass(int x, int y)
{
X = x;
Y = y;
}
}
MainWindow.xaml.cs
public partial class MainWindow : Window
{
private ViewModel _viewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = _viewModel;
}
private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
{
Ellipse s = (Ellipse)sender;
s.Fill = Brushes.Green;
}
private void Ellipse_MouseLeave(object sender, MouseEventArgs e)
{
Ellipse s = (Ellipse)sender;
s.Fill = Brushes.Black;
}
}
MainWindow.xaml
<Window x:Class="TestSO33742236WpfNestedCollection.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:TestSO33742236WpfNestedCollection"
Loaded="Window_Loaded"
Title="MainWindow" Height="350" Width="525">
<ItemsControl ItemsSource="{Binding Path=Layers}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="LightBlue">
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type c:LayerClass}">
<ItemsControl ItemsSource="{Binding Path=Markers}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="myCanvas"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="20" Height="20" Fill="Black" MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<p:Style> <!-- Explicit namespace to workaround StackOverflow XML formatting bug -->
<Setter Property="Canvas.Left" Value="{Binding Path=X}"></Setter>
<Setter Property="Canvas.Top" Value="{Binding Path=Y}"></Setter>
</p:Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
【问题讨论】:
-
如果你想要不透明的背景,你应该把它放在图层堆栈后面/外部的元素/图层(例如边框)上,并使画布本身保持透明。另外,请查看
Canvas IsItemsHost=true属性,因为它可能会有所不同。 -
如果可能的话,我只想使用一个 mainCanvas。第二件事:设置 innerCanvases 以填充 mainCanvas 的所有空间,因此它们将始终具有相同的尺寸。