未在 WPF DataTemplate 中绘制线
Line not being Drawn in WPF DataTemplate
我正在尝试收集正确的 WPF 数据模板以获得一个列表视图,每个项目都有一个 Border+Canvas(参见 ),然后在最后的每个项目 Canvas 上画一条线节点集合。它几乎可以工作,但目前我没有在 canvas 上绘制线条:在调试输出 Window 中,我看到:
System.Windows.Data Error: 40 : BindingExpression path error: 'CalloutGroup' property not found on 'object' ''CalloutGroup' (HashCode=35061213)'. BindingExpression:Path=CalloutGroup; DataItem='CalloutGroup' (HashCode=35061213); target element is 'ItemsControl' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
这里是MainWindow.Xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CalloutControl" x:Class="CalloutControl.MainWindow"
Title="MainWindow" Height="430.597" Width="525">
<Window.Resources>
<DataTemplate x:Key="LineTemplate">
<Line X1 ="{Binding X}" X2="{Binding X}" Stroke="Wheat"
StrokeThickness="10" Y1="{Binding Y}" Y2="{Binding Y}"/>
</DataTemplate>
<DataTemplate x:Key="GroupTemplate">
<Border Width="200" Height ="{Binding DistributionHeight}" BorderThickness="5" Background="Brown" BorderBrush="Red">
<ItemsControl ItemsSource="{Binding Path=CalloutGroup}"
ItemTemplate="{StaticResource LineTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Beige"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<Border>
<ListView ItemsSource="{Binding Groups}"
ItemTemplate="{StaticResource GroupTemplate}">
</ListView>
</Border>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CalloutControl
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new MainWindowViewModel();
DataContext = vm;
}
}
}
然后是 ViewModel -> MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
namespace CalloutControl
{
public class CalloutItem : INotifyPropertyChanged
{
public CalloutItem()
{
}
public CalloutItem (int length,
int itemNum,
double x,
double y ){
Length = length;
ItemNum = itemNum;
X = x;
Y = y;
}
private int length;
public int Length
{
get { return length; }
set
{
length = value;
OnPropertyChanged("Length");
}
}
private int itemNum;
public int ItemNum
{
get { return itemNum; }
set { itemNum = value;
OnPropertyChanged("ItemNum");
}
}
//public int ItemNum;
private double x;
public double X
{
get { return x; }
set { x = value;
OnPropertyChanged("X");
}
}
private double y;
public double Y
{
get { return y; }
set { y = value;
OnPropertyChanged("Y");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class CalloutGroup : INotifyPropertyChanged
{
ObservableCollection<CalloutItem> group = new ObservableCollection<CalloutItem>();
public CalloutGroup(int nItems)
{
NumItems = nItems;
}
public ObservableCollection<CalloutItem> Group
{
get { return group; }
set
{
group = value;
OnPropertyChanged("Group");
}
}
private double distributionHeight = 400;
public double DistributionHeight
{
get { return distributionHeight; }
set
{
distributionHeight = value;
Redistribute();
OnPropertyChanged("DistributionHeight");
}
}
private void Redistribute()
{
double step = distributionHeight / numItems;
double currY = step / 2 ;
var redistArr = group.ToArray();
for (int i = 0; i < group.Count(); i++)
{
redistArr[i].Y = currY;
currY += step;
}
OnPropertyChanged("Group");
}
private int numItems = 10;
public int NumItems
{
get { return numItems; }
set
{
numItems = value;
group.Clear();
for (int i = 0; i < numItems; i++)
{
group.Add(new CalloutItem());
}
Redistribute();
OnPropertyChanged("NumItems");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class MainWindowViewModel : INotifyPropertyChanged
{
ObservableCollection<CalloutGroup> groups = new ObservableCollection<CalloutGroup>();
public ObservableCollection<CalloutGroup> Groups
{
get { return groups; }
set { groups = value;
OnPropertyChanged("Groups");
}
}
public MainWindowViewModel ()
{
groups.Add(new CalloutGroup(3));
groups.Add(new CalloutGroup(3));
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
您似乎缺少 X1 绑定中的 {}
您的代码有问题:
行有相同的StartPoint
和EndPoint
,所以即使没有其他错误,这个点也不会出现。
在您的项目模板中,而不是
<ItemsControl ItemsSource="{Binding Group}"
您使用:
<ItemsControl ItemsSource="{Binding Path=CalloutGroup}"`
这里是稍微修改过的代码,我在你的代码中添加了 X2、Y2。您可以根据需要进行更改。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CalloutControl
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new MainWindowViewModel();
vm.Groups.Add(new CalloutControl.CalloutGroup(2));
vm.Groups.Add(new CalloutControl.CalloutGroup(2));
vm.Groups[0].Group.Add(new CalloutControl.CalloutItem(10, 1, 0, 100, 200, 100));
vm.Groups[0].Group.Add(new CalloutControl.CalloutItem(10, 2, 100, 0, 100, 200));
vm.Groups[1].Group.Add(new CalloutControl.CalloutItem(10, 1, 100, 0, 200, 100));
vm.Groups[1].Group.Add(new CalloutControl.CalloutItem(10, 2, 100, 200, 200, 100));
DataContext = vm;
}
}
}
namespace CalloutControl
{
public class CalloutItem : INotifyPropertyChanged
{
public CalloutItem()
{
}
public CalloutItem(int length,
int itemNum,
double _x1,
double _y1,
double _x2,
double _y2)
{
Length = length;
ItemNum = itemNum;
X1 = _x1;
Y1 = _y1;
X2 = _x2;
Y2 = _y2;
}
private int length;
public int Length
{
get { return length; }
set
{
length = value;
OnPropertyChanged("Length");
}
}
private int itemNum;
public int ItemNum
{
get { return itemNum; }
set
{
itemNum = value;
OnPropertyChanged("ItemNum");
}
}
//public int ItemNum;
private double x1;
public double X1
{
get { return x1; }
set
{
x1 = value;
OnPropertyChanged("X1");
}
}
private double y1;
public double Y1
{
get { return y1; }
set
{
y1 = value;
OnPropertyChanged("Y1");
}
}
private double x2;
public double X2
{
get { return x2; }
set
{
x2 = value;
OnPropertyChanged("X2");
}
}
private double y2;
public double Y2
{
get { return y2; }
set
{
y2 = value;
OnPropertyChanged("Y2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class CalloutGroup : INotifyPropertyChanged
{
ObservableCollection<CalloutItem> group = new ObservableCollection<CalloutItem>();
public CalloutGroup(int nItems)
{
NumItems = nItems;
}
public ObservableCollection<CalloutItem> Group
{
get { return group; }
set
{
group = value;
OnPropertyChanged("Group");
}
}
private double distributionHeight = 200;
public double DistributionHeight
{
get { return distributionHeight; }
set
{
distributionHeight = value;
Redistribute();
OnPropertyChanged("DistributionHeight");
}
}
private void Redistribute()
{
double step = distributionHeight / numItems;
double currY = step / 2;
var redistArr = group.ToArray();
for (int i = 0; i < group.Count(); i++)
{
redistArr[i].Y1 = currY;
currY += step;
}
OnPropertyChanged("Group");
}
private int numItems = 10;
public int NumItems
{
get { return numItems; }
set
{
numItems = value;
group.Clear();
for (int i = 0; i < numItems; i++)
{
//group.Add(new CalloutItem());
}
Redistribute();
OnPropertyChanged("NumItems");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class MainWindowViewModel : INotifyPropertyChanged
{
ObservableCollection<CalloutGroup> groups = new ObservableCollection<CalloutGroup>();
public ObservableCollection<CalloutGroup> Groups
{
get { return groups; }
set
{
groups = value;
OnPropertyChanged("Groups");
}
}
public MainWindowViewModel()
{
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
XAML:
<Window.Resources>
<DataTemplate x:Key="LineTemplate">
<Line X1="{Binding X1}" X2="{Binding X2}"
Y1="{Binding Y1}" Y2="{Binding Y2}"
Stroke="Blue"
StrokeThickness="10" />
</DataTemplate>
<DataTemplate x:Key="GroupTemplate">
<Border BorderThickness="5" Background="Brown" BorderBrush="Red">
<ItemsControl ItemsSource="{Binding Group}"
ItemTemplate="{StaticResource LineTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent" Width="200" Height="{Binding DistributionHeight}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<Border>
<ListView ItemsSource="{Binding Groups}" ItemTemplate="{StaticResource GroupTemplate}">
</ListView>
</Border>
</Grid>
我正在尝试收集正确的 WPF 数据模板以获得一个列表视图,每个项目都有一个 Border+Canvas(参见 ),然后在最后的每个项目 Canvas 上画一条线节点集合。它几乎可以工作,但目前我没有在 canvas 上绘制线条:在调试输出 Window 中,我看到:
System.Windows.Data Error: 40 : BindingExpression path error: 'CalloutGroup' property not found on 'object' ''CalloutGroup' (HashCode=35061213)'. BindingExpression:Path=CalloutGroup; DataItem='CalloutGroup' (HashCode=35061213); target element is 'ItemsControl' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
这里是MainWindow.Xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CalloutControl" x:Class="CalloutControl.MainWindow"
Title="MainWindow" Height="430.597" Width="525">
<Window.Resources>
<DataTemplate x:Key="LineTemplate">
<Line X1 ="{Binding X}" X2="{Binding X}" Stroke="Wheat"
StrokeThickness="10" Y1="{Binding Y}" Y2="{Binding Y}"/>
</DataTemplate>
<DataTemplate x:Key="GroupTemplate">
<Border Width="200" Height ="{Binding DistributionHeight}" BorderThickness="5" Background="Brown" BorderBrush="Red">
<ItemsControl ItemsSource="{Binding Path=CalloutGroup}"
ItemTemplate="{StaticResource LineTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Beige"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<Border>
<ListView ItemsSource="{Binding Groups}"
ItemTemplate="{StaticResource GroupTemplate}">
</ListView>
</Border>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CalloutControl
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new MainWindowViewModel();
DataContext = vm;
}
}
}
然后是 ViewModel -> MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
namespace CalloutControl
{
public class CalloutItem : INotifyPropertyChanged
{
public CalloutItem()
{
}
public CalloutItem (int length,
int itemNum,
double x,
double y ){
Length = length;
ItemNum = itemNum;
X = x;
Y = y;
}
private int length;
public int Length
{
get { return length; }
set
{
length = value;
OnPropertyChanged("Length");
}
}
private int itemNum;
public int ItemNum
{
get { return itemNum; }
set { itemNum = value;
OnPropertyChanged("ItemNum");
}
}
//public int ItemNum;
private double x;
public double X
{
get { return x; }
set { x = value;
OnPropertyChanged("X");
}
}
private double y;
public double Y
{
get { return y; }
set { y = value;
OnPropertyChanged("Y");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class CalloutGroup : INotifyPropertyChanged
{
ObservableCollection<CalloutItem> group = new ObservableCollection<CalloutItem>();
public CalloutGroup(int nItems)
{
NumItems = nItems;
}
public ObservableCollection<CalloutItem> Group
{
get { return group; }
set
{
group = value;
OnPropertyChanged("Group");
}
}
private double distributionHeight = 400;
public double DistributionHeight
{
get { return distributionHeight; }
set
{
distributionHeight = value;
Redistribute();
OnPropertyChanged("DistributionHeight");
}
}
private void Redistribute()
{
double step = distributionHeight / numItems;
double currY = step / 2 ;
var redistArr = group.ToArray();
for (int i = 0; i < group.Count(); i++)
{
redistArr[i].Y = currY;
currY += step;
}
OnPropertyChanged("Group");
}
private int numItems = 10;
public int NumItems
{
get { return numItems; }
set
{
numItems = value;
group.Clear();
for (int i = 0; i < numItems; i++)
{
group.Add(new CalloutItem());
}
Redistribute();
OnPropertyChanged("NumItems");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class MainWindowViewModel : INotifyPropertyChanged
{
ObservableCollection<CalloutGroup> groups = new ObservableCollection<CalloutGroup>();
public ObservableCollection<CalloutGroup> Groups
{
get { return groups; }
set { groups = value;
OnPropertyChanged("Groups");
}
}
public MainWindowViewModel ()
{
groups.Add(new CalloutGroup(3));
groups.Add(new CalloutGroup(3));
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
您似乎缺少 X1 绑定中的 {}
您的代码有问题:
行有相同的StartPoint
和EndPoint
,所以即使没有其他错误,这个点也不会出现。
在您的项目模板中,而不是
<ItemsControl ItemsSource="{Binding Group}"
您使用:
<ItemsControl ItemsSource="{Binding Path=CalloutGroup}"`
这里是稍微修改过的代码,我在你的代码中添加了 X2、Y2。您可以根据需要进行更改。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CalloutControl
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new MainWindowViewModel();
vm.Groups.Add(new CalloutControl.CalloutGroup(2));
vm.Groups.Add(new CalloutControl.CalloutGroup(2));
vm.Groups[0].Group.Add(new CalloutControl.CalloutItem(10, 1, 0, 100, 200, 100));
vm.Groups[0].Group.Add(new CalloutControl.CalloutItem(10, 2, 100, 0, 100, 200));
vm.Groups[1].Group.Add(new CalloutControl.CalloutItem(10, 1, 100, 0, 200, 100));
vm.Groups[1].Group.Add(new CalloutControl.CalloutItem(10, 2, 100, 200, 200, 100));
DataContext = vm;
}
}
}
namespace CalloutControl
{
public class CalloutItem : INotifyPropertyChanged
{
public CalloutItem()
{
}
public CalloutItem(int length,
int itemNum,
double _x1,
double _y1,
double _x2,
double _y2)
{
Length = length;
ItemNum = itemNum;
X1 = _x1;
Y1 = _y1;
X2 = _x2;
Y2 = _y2;
}
private int length;
public int Length
{
get { return length; }
set
{
length = value;
OnPropertyChanged("Length");
}
}
private int itemNum;
public int ItemNum
{
get { return itemNum; }
set
{
itemNum = value;
OnPropertyChanged("ItemNum");
}
}
//public int ItemNum;
private double x1;
public double X1
{
get { return x1; }
set
{
x1 = value;
OnPropertyChanged("X1");
}
}
private double y1;
public double Y1
{
get { return y1; }
set
{
y1 = value;
OnPropertyChanged("Y1");
}
}
private double x2;
public double X2
{
get { return x2; }
set
{
x2 = value;
OnPropertyChanged("X2");
}
}
private double y2;
public double Y2
{
get { return y2; }
set
{
y2 = value;
OnPropertyChanged("Y2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class CalloutGroup : INotifyPropertyChanged
{
ObservableCollection<CalloutItem> group = new ObservableCollection<CalloutItem>();
public CalloutGroup(int nItems)
{
NumItems = nItems;
}
public ObservableCollection<CalloutItem> Group
{
get { return group; }
set
{
group = value;
OnPropertyChanged("Group");
}
}
private double distributionHeight = 200;
public double DistributionHeight
{
get { return distributionHeight; }
set
{
distributionHeight = value;
Redistribute();
OnPropertyChanged("DistributionHeight");
}
}
private void Redistribute()
{
double step = distributionHeight / numItems;
double currY = step / 2;
var redistArr = group.ToArray();
for (int i = 0; i < group.Count(); i++)
{
redistArr[i].Y1 = currY;
currY += step;
}
OnPropertyChanged("Group");
}
private int numItems = 10;
public int NumItems
{
get { return numItems; }
set
{
numItems = value;
group.Clear();
for (int i = 0; i < numItems; i++)
{
//group.Add(new CalloutItem());
}
Redistribute();
OnPropertyChanged("NumItems");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class MainWindowViewModel : INotifyPropertyChanged
{
ObservableCollection<CalloutGroup> groups = new ObservableCollection<CalloutGroup>();
public ObservableCollection<CalloutGroup> Groups
{
get { return groups; }
set
{
groups = value;
OnPropertyChanged("Groups");
}
}
public MainWindowViewModel()
{
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
XAML:
<Window.Resources>
<DataTemplate x:Key="LineTemplate">
<Line X1="{Binding X1}" X2="{Binding X2}"
Y1="{Binding Y1}" Y2="{Binding Y2}"
Stroke="Blue"
StrokeThickness="10" />
</DataTemplate>
<DataTemplate x:Key="GroupTemplate">
<Border BorderThickness="5" Background="Brown" BorderBrush="Red">
<ItemsControl ItemsSource="{Binding Group}"
ItemTemplate="{StaticResource LineTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent" Width="200" Height="{Binding DistributionHeight}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<Border>
<ListView ItemsSource="{Binding Groups}" ItemTemplate="{StaticResource GroupTemplate}">
</ListView>
</Border>
</Grid>