我看了几个关于这个话题的答案,但我还是不明白,请问如何在ContentTemplate中从不同的ObservableCollection集合绑定到每个canvas?如何在ContentTemplate中把不同的ObservableCollection集合绑定到每个画布上?
<TabControl x:Name="Drawing_TabControl"
Grid.Row="0"
Background="WhiteSmoke"
SelectionChanged="Drawing_TabControl_SelectionChanged"
ItemsSource="{Binding New_File_Models}"
SelectedItem="{Binding Selected_File_Model}">
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
Background="Transparent">
<TextBlock Text="{Binding Path=Header}" Background="Transparent" />
<Button Height="18"
Width="18"
Background="Transparent"
BorderBrush="Transparent"
Click="Close_TabItem"
Visibility="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=TabItem},
Converter={StaticResource B2V}}">
<Image Source="icons\close_x.png"/>
</Button>
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Grid Background="WhiteSmoke">
<Canvas x:Name="a"
Background="GhostWhite"
Height="6cm"
Width="16cm"
HorizontalAlignment="Center"
VerticalAlignment="Center">
</Canvas>
<Canvas x:Name="b"
Background="Transparent"
Height="6cm"
Width="16cm"
HorizontalAlignment="Center"
VerticalAlignment="Center"
SizeChanged="gridCanvas_SizeChanged"></Canvas>
<Border BorderBrush="Black"
BorderThickness="0.5 0.5 0.5 0.5"
Height="4cm"
Width="14cm"
HorizontalAlignment="Center"
VerticalAlignment="Center"></Border>
<Canvas x:Name="c"
Background="White"
Height="4cm"
Width="14cm"
HorizontalAlignment="Center"
VerticalAlignment="Center"></Canvas>
<Canvas x:Name="d"
Background="Transparent"
Height="4cm"
Width="14cm"
HorizontalAlignment="Center"
VerticalAlignment="Center"></Canvas>
<Canvas x:Name="e"
Background="Transparent"
Height="4cm"
Width="14cm"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ClipToBounds="True"></Canvas>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
任务如下。1.各种几何形状(Ellipse
, Line
, Rectangle
等)都画在上面。Canvas x:Name="e"
. 这些数据将被保存到一个文件中。2.其他画布是辅助绘制静态数据,如标记、网格等,它们不会被保存到文件中。
在研究了 嵌套式观测集合的答案。首先,我重新设计了XAML标记,将其替换为 canvas
与 listbox
:
<Window.Resources>
<DataTemplate x:Key="EllipseTemplate"
DataType="{x:Type local2:Figure_M}">
<ItemsControl ItemsSource="{Binding Path=Ellipses}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local3:Ellipse_M}">
<Ellipse Stroke="Black"
StrokeThickness="1"
Width="{Binding Width}"
Height="{Binding Height}"
Cursor="Hand" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
<DataTemplate x:Key="LineTemplate"
DataType="{x:Type local2:Figure_M}">
<ItemsControl ItemsSource="{Binding Path=Lines}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local3:Line_M}">
<Line Stroke="Black"
StrokeThickness="1"
X1="{Binding X1}"
X2="{Binding X2}"
Y1="{Binding Y1}"
Y2="{Binding Y2}"
Cursor="Hand" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
<DataTemplate x:Key="RectangleTemplate"
DataType="{x:Type local2:Figure_M}">
<ItemsControl ItemsSource="{Binding Path=Rectangles}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local3:Rectangle_M}">
<Rectangle Stroke="Black"
StrokeThickness="1"
Width="{Binding Width}"
Height="{Binding Height}"
Cursor="Hand" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</Window.Resources>
<TabControl x:Name="Drawing_TabControl"
Grid.Row="0"
Background="WhiteSmoke"
SelectionChanged="Drawing_TabControl_SelectionChanged"
ItemsSource="{Binding Files}"
SelectedItem="{Binding SelectedFile_M}">
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type local1:File_M}">
<StackPanel Orientation="Horizontal"
Background="Transparent">
<TextBlock Text="{Binding Path=Name_File}" Background="Transparent" />
<Button Height="18"
Width="18"
Background="Transparent"
BorderBrush="Transparent"
Click="Close_TabItem"
Visibility="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=TabItem},
Converter={StaticResource B2V}}">
<Image Source="icons\close_x.png"/>
</Button>
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type local1:File_M}">
<Grid Background="WhiteSmoke">
<Grid>
<Canvas x:Name="a"
Background="GhostWhite"
Height="6cm"
Width="16cm"
HorizontalAlignment="Center"
VerticalAlignment="Center">
</Canvas>
<Canvas x:Name="b"
Background="Transparent"
Height="6cm"
Width="16cm"
HorizontalAlignment="Center"
VerticalAlignment="Center"
SizeChanged="gridCanvas_SizeChanged"></Canvas>
<Border BorderBrush="Black"
BorderThickness="0.5 0.5 0.5 0.5"
Height="4cm"
Width="14cm"
HorizontalAlignment="Center"
VerticalAlignment="Center"></Border>
<Canvas x:Name="c"
Background="White"
Height="4cm"
Width="14cm"
HorizontalAlignment="Center"
VerticalAlignment="Center"></Canvas>
<Canvas x:Name="d"
Background="Transparent"
Height="4cm"
Width="14cm"
HorizontalAlignment="Center"
VerticalAlignment="Center"></Canvas>
</Grid>
<ListBox ItemsSource="{Binding Path=Figures}"
SelectedItem="{Binding Path=SelectedFigure_M}"
SelectionMode="Multiple"
Background="Transparent"
Height="4cm"
Width="14cm"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplateSelector>
<local:FigureTemplateSelector EllipseTemplate="{StaticResource EllipseTemplate}"
LineTemplate="{StaticResource LineTemplate}"
RectangleTemplate="{StaticResource RectangleTemplate}" />
</ListBox.ItemTemplateSelector>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Canvas.Left"
Value="{Binding X}" />
<Setter Property="Canvas.Top"
Value="{Binding Y}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border"
BorderThickness="1"
Padding="1">
<ContentPresenter Name="Content" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="true">
<Setter TargetName="Border"
Property="BorderBrush"
Value="Blue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
接下来我创建了一个数据模型。
class Ellipse_M :
public class Ellipse_M : INotifyPropertyChanged
{
#region DataMembers
private double x = 0;
private double y = 0;
private double width = 0;
private double height = 0;
#endregion DataMembers
public double X
{
get
{
return x;
}
set
{
if (x == value)
{
return;
}
x = value;
OnPropertyChanged("X");
}
}
public double Y
{
get
{
return y;
}
set
{
if (y == value)
{
return;
}
y = value;
OnPropertyChanged("Y");
}
}
public double Width
{
get
{
return width;
}
set
{
if (width == value)
{
return;
}
width = value;
OnPropertyChanged("Width");
}
}
public double Height
{
get
{
return height;
}
set
{
if (height == value)
{
return;
}
height = value;
OnPropertyChanged("Height");
}
}
#region INotifyPropertyChanged Members
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
類線條_M。
public class Line_M : INotifyPropertyChanged
{
#region DataMembers
private double x1 = 0;
private double y1 = 0;
private double x2 = 0;
private double y2 = 0;
#endregion DataMembers
public double X1
{
get
{
return x1;
}
set
{
if (x1 == value)
{
return;
}
x1 = value;
OnPropertyChanged("X1");
}
}
public double Y1
{
get
{
return y1;
}
set
{
if (y1 == value)
{
return;
}
y1 = value;
OnPropertyChanged("Y1");
}
}
public double X2
{
get
{
return x2;
}
set
{
if (x2 == value)
{
return;
}
x2 = value;
OnPropertyChanged("X2");
}
}
public double Y2
{
get
{
return y2;
}
set
{
if (y2 == value)
{
return;
}
y2 = value;
OnPropertyChanged("Y1");
}
}
#region INotifyPropertyChanged Members
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
类 矩形_M : 类 矩形_M :
public class Rectangle_M : INotifyPropertyChanged
{
#region DataMembers
private double x = 0;
private double y = 0;
private double width = 0;
private double height = 0;
#endregion DataMembers
public double X
{
get
{
return x;
}
set
{
if (x == value)
{
return;
}
x = value;
OnPropertyChanged("X");
}
}
public double Y
{
get
{
return y;
}
set
{
if (y == value)
{
return;
}
y = value;
OnPropertyChanged("Y");
}
}
public double Width
{
get
{
return width;
}
set
{
if (width == value)
{
return;
}
width = value;
OnPropertyChanged("Width");
}
}
public double Height
{
get
{
return height;
}
set
{
if (height == value)
{
return;
}
height = value;
OnPropertyChanged("Height");
}
}
#region INotifyPropertyChanged Members
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
类 Figure_M : 类 Figure_M :
public class Figure_M : INotifyPropertyChanged
{
#region DataMembers(Ellipse_M, Line_M, Rectangle_M)
private double x = 0;
private double y = 0;
private Ellipse_M selectedEllipse_M;
private Line_M selectedLine_M;
private Rectangle_M selectedRectangle_M;
private string selectedFigure = "";
#endregion DataMembers(Ellipse_M, Line_M, Rectangle_M)
public Figure_M()
{
Ellipses = new ObservableCollection<Ellipse_M>();
Lines = new ObservableCollection<Line_M>();
Rectangles = new ObservableCollection<Rectangle_M>();
}
#region Property of Collections
public ObservableCollection<Ellipse_M> Ellipses { get; set; }
public ObservableCollection<Line_M> Lines { get; set; }
public ObservableCollection<Rectangle_M> Rectangles { get; set; }
#endregion Property of Collections
#region Property of DataMembers
public Ellipse_M SelectedEllipse_M
{
get { return selectedEllipse_M; }
set
{
if (value != selectedEllipse_M)
{
selectedEllipse_M = value;
OnPropertyChanged();
}
}
}
public Line_M SelectedLine_M
{
get { return selectedLine_M; }
set
{
if (value != selectedLine_M)
{
selectedLine_M = value;
OnPropertyChanged();
}
}
}
public Rectangle_M SelectedRectangle_M
{
get { return selectedRectangle_M; }
set
{
if (value != selectedRectangle_M)
{
selectedRectangle_M = value;
OnPropertyChanged();
}
}
}
public string SelectedFigure
{
get { return selectedFigure; }
set
{
selectedFigure = value;
}
}
public double X
{
get { return x; }
set
{
if (value != x)
{
x = value;
OnPropertyChanged();
}
}
}
public double Y
{
get { return y; }
set
{
if (value != y)
{
y = value;
OnPropertyChanged();
}
}
}
#endregion Property of DataMembers
#region INotifyPropertyChanged Members
/// <summary>
/// Raises the 'PropertyChanged' event when the value of a property of the view model has changed.
/// </summary>
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
类File_M:类File_M。
public class File_M : INotifyPropertyChanged
{
#region DataMembers
private string name_File;
private Figure_M selectedFigure_M;
#endregion DataMembers
public string Name_File
{
get { return name_File; }
set
{
name_File = value;
OnPropertyChanged("Name_File");
}
}
public File_M()
{
Figures = new ObservableCollection<Figure_M>();
}
#region Property of Collections
public ObservableCollection<Figure_M> Figures { get; set; }
#endregion Property of Collections
#region Property of DataMembers
public Figure_M SelectedFigure_M
{
get { return selectedFigure_M; }
set
{
if (value != selectedFigure_M)
{
selectedFigure_M = value;
OnPropertyChanged();
}
}
}
#endregion Property of DataMembers
#region INotifyPropertyChanged Members
/// <summary>
/// Raises the 'PropertyChanged' event when the value of a property of the view model has changed.
/// </summary>
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
ViewModel。
public class ViewModel : INotifyPropertyChanged
{
#region DataMembers
private File_M selectedFile_M;
#endregion DataMembers
public ViewModel()
{
Files = new ObservableCollection<File_M>();
for(int i = 0; i < 3; i++)
{
File_M file_M = new File_M();
file_M.Name_File = $"Макет_{i + 1}";
for (int j = 3; j >= 0; j--)
{
Figure_M figure_M = new Figure_M();
Ellipse_M ellipse_M = new Ellipse_M();
ellipse_M.Height = 25 + j * 50;
ellipse_M.Width = 35 + j * 50;
figure_M.X = 70 + j*80;
figure_M.Y = 50;
figure_M.Ellipses.Add(ellipse_M);
file_M.Figures.Add(figure_M);
}
for (int j = 3; j >= 0; j--)
{
Figure_M figure_M = new Figure_M();
Line_M line_M = new Line_M();
line_M.X2 = 100 + j * 80;
line_M.Y2 = 100;
figure_M.X = 10 + j * 80;
figure_M.Y = 10;
figure_M.Lines.Add(line_M);
file_M.Figures.Add(figure_M);
}
for (int j = 3; j >= 0; j--)
{
Figure_M figure_M = new Figure_M();
Rectangle_M rectangle_M = new Rectangle_M();
rectangle_M.Height = 25 + j * 20;
rectangle_M.Width = 35 + j * 20;
figure_M.X = 70 + j * 80;
figure_M.Y = 50;
figure_M.Rectangles.Add(rectangle_M);
file_M.Figures.Add(figure_M);
}
Files.Add(file_M);
}
}
public ObservableCollection<File_M> Files { get; set; }
#region Property of DataMembers
public File_M SelectedFile_M
{
get { return selectedFile_M; }
set
{
if (value != selectedFile_M)
{
selectedFile_M = value;
OnPropertyChanged();
}
}
}
#endregion Property of DataMembers
#region INotifyPropertyChanged Members
/// <summary>
/// Raises the 'PropertyChanged' event when the value of a property of the view model has changed.
/// </summary>
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
为了能够选择此刻要放置的形状,我创建了 FigureTemplateSelector 。
public class FigureTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
DataTemplate template = null;
Figure_M figure_M = item as Figure_M;
if (figure_M.Ellipses.Count > 0)
{
template = EllipseTemplate;
if (template == null)
{
template = base.SelectTemplate(item, container);
}
}
else if(figure_M.Lines.Count > 0)
{
template = LineTemplate;
if (template == null)
{
template = base.SelectTemplate(item, container);
}
}
else if (figure_M.Rectangles.Count > 0)
{
template = RectangleTemplate;
if (template == null)
{
template = base.SelectTemplate(item, container);
}
}
else
{
template = base.SelectTemplate(item, container);
}
return template;
}
public DataTemplate EllipseTemplate { get; set; }
public DataTemplate LineTemplate { get; set; }
public DataTemplate RectangleTemplate { get; set; }
}
其他的画布都是辅助性的,所以我认为我们也应该这样做,在里面创建一个集合。Figure
类。