Это вопрос типа «что я делаю неправильно». Я перевел свою проблему в простое приложение для проверки концепции. Я приведу код ниже.
В двух словах: у меня есть ItemsControl в ScrollViewer. В этом ItemsControl я хочу поместить несколько типов вещей. Я создаю CompositeCollection в ItemsControl.ItemSource для содержания. Для примера у меня есть коллекция объектов, каждый из которых является в основном меткой. У меня также есть строка, значения которой жестко закодированы. Наконец, у меня есть строка, конечные точки которой я хотел бы связать, чтобы я мог их динамически изменять.
CompositeCollection не имеет свойства DataContext, поскольку оно не является производным от FrameworkElement, поэтому операторы привязки должны включать источник , Для коллекции объектов я создал CollectionViewSource в ресурсах ItemsControl. Затем я ссылаюсь на это как на источник, когда связываю коллекцию объектов в CompositCollection. Это хорошо работает.
Жестко запрограммированная линия также хорошо работает, поэтому я знаю, что могу нарисовать линию.
Проблема заключается в связанной линии. Я попытался сослаться на источник напрямую, указав путь к нужным мне данным. Затем я попытался создать CollectionViewSource, как сделал для коллекции объектов. Ни один из них не работал. Я чувствую, что я рядом, просто что-то упускаю. Может кто-нибудь меня расклеит?
Даг
Код следующий:
MainWindow.xaml
<Window x:Class="POC_WPF_CompositeCollection_Binding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:POC_WPF_CompositeCollection_Binding"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="700">
<Window.Resources>
<local:MainWindowResource x:Key="MainWindowResource"/>
<DataTemplate DataType="{x:Type local:NowLineArt}">
<Line
X1="{Binding AX, Mode=TwoWay}"
Y1="{Binding AY, Mode=TwoWay}"
X2="{Binding BX, Mode=TwoWay}"
Y2="{Binding BY, Mode=TwoWay}"
Stroke="Red"
StrokeThickness="6">
</Line>
</DataTemplate>
<DataTemplate DataType="{x:Type local:LoadIdArt}">
<Canvas>
<Label
Canvas.Top="{Binding Top, Mode=TwoWay}"
Content="{Binding Content, Mode=TwoWay}"
Canvas.Left="5"
Width="100"
Height="25"
Focusable="False"
FontFamily="Arial"
FontSize="16"
FontWeight="Bold"
Foreground="Black">
</Label>
</Canvas>
</DataTemplate>
</Window.Resources>
<ScrollViewer
x:Name="scroller"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible"
MouseMove="Scroller_MouseMove">
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas
x:Name="ContentCanvas"
Background="Aquamarine"
Width="600"
Height="400">
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Resources>
<CollectionViewSource x:Key="LoadIdCollection" Source="{Binding LoadIdCol}"/>
<CollectionViewSource x:Key="LineResource" Source="{Binding NowLine}"/>
</ItemsControl.Resources>
<ItemsControl.ItemsSource>
<CompositeCollection>
<!--The CompositeCollection class does not derive from FrameworkElement
and thus does not have a DataContext property to support data
binding. It will only work if you use Binding providing a Source.-->
<CollectionContainer Collection="{Binding Source={StaticResource LoadIdCollection}}"/>
<Line X1="0" Y1="0" X2="600" Y2="400" Stroke="Green" StrokeThickness="6"/>
<!--<Line X1="{Binding Source={StaticResource MainWindowResource}, Path=NowLine.AX}"
Y1="{Binding Source={StaticResource MainWindowResource}, Path=NowLine.AY}"
X2="{Binding Source={StaticResource MainWindowResource}, Path=NowLine.BX}"
Y2="{Binding Source={StaticResource MainWindowResource}, Path=NowLine.BY}"
Stroke="Red" StrokeThickness="6"/>-->
<Line X1="{Binding Source={StaticResource LineResource}, Path=AX}"
Y1="{Binding Source={StaticResource LineResource}, Path=AY}"
X2="{Binding Source={StaticResource LineResource}, Path=BX}"
Y2="{Binding Source={StaticResource LineResource}, Path=BY}"
Stroke="Red" StrokeThickness="6"/>
</CompositeCollection>
</ItemsControl.ItemsSource>
</ItemsControl>
</ScrollViewer>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace POC_WPF_CompositeCollection_Binding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private MainWindowResource _resource = null;
private Point _mouseInScroll = new Point(0.0, 0.0);
public MainWindow()
{
LoadIdArt loadIdArt = null;
NowLineArt nowLineArt = null;
InitializeComponent();
// get a reference to the binding sources so we can set the properties
_resource = new MainWindowResource();
this.DataContext = _resource;
loadIdArt = new LoadIdArt(40, "First");
_resource.LoadIdCol.Add(loadIdArt);
loadIdArt = new LoadIdArt(80, "Second");
_resource.LoadIdCol.Add(loadIdArt);
loadIdArt = new LoadIdArt(120, "Third");
_resource.LoadIdCol.Add(loadIdArt);
nowLineArt = new NowLineArt(600, 0, 0, 400);
_resource.NowLine = nowLineArt;
}
private void Scroller_MouseMove(object sender, MouseEventArgs e)
{
ScrollViewer scrollViewer = sender as ScrollViewer;
// if the mouse is over the scrollviewer...
if (scrollViewer.IsMouseOver)
{
// save the position
_mouseInScroll = e.GetPosition(scrollViewer);
}
}
}
}
MainWindowResource.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace POC_WPF_CompositeCollection_Binding
{
class MainWindowResource : INotifyPropertyChanged
{
#region Private Members
private ObservableCollection<LoadIdArt> _loadIdCol = null;
private NowLineArt _nowLine = null;
#endregion Private Members
#region Constructor
public MainWindowResource()
{
_loadIdCol = new ObservableCollection<LoadIdArt>();
_nowLine = new NowLineArt();
}
#endregion Constructor
#region Drawable Objects
public ObservableCollection<LoadIdArt> LoadIdCol
{
get { return _loadIdCol; }
set
{
_loadIdCol = value;
OnPropertyChanged("LoadIdCol");
}
}
public NowLineArt NowLine
{
get { return _nowLine; }
set
{
_nowLine = value;
OnPropertyChanged("NowLine");
}
}
#endregion Drawable Objects
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion PropertyChanged
}
}
LoadIdArt.cs
using System.ComponentModel;
namespace POC_WPF_CompositeCollection_Binding
{
class LoadIdArt : INotifyPropertyChanged
{
#region Constructors
public LoadIdArt() { }
public LoadIdArt(
double top,
string content
)
{
Top = top;
Content = content;
}
#endregion Constructors
#region Depenency Properties
/// <summary>
/// Top
/// </summary>
private double _top = 0.0;
public double Top
{
get { return _top; }
set { _top = value; OnPropertyChanged("Top"); }
}
/// <summary>
/// Content
/// </summary>
private string _content = "";
public string Content
{
get { return _content; }
set { _content = value; OnPropertyChanged("Content"); }
}
#endregion Depenency Properties
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion PropertyChanged
}
}
NowLineArt.cs
using System.ComponentModel;
namespace POC_WPF_CompositeCollection_Binding
{
class NowLineArt : INotifyPropertyChanged
{
#region Constructors
public NowLineArt() { }
public NowLineArt(double ax, double ay, double bx, double by)
{
AX = ax;
AY = ay;
BX = bx;
BY = by;
}
#endregion Constructors
#region Dependency Properties
// AX
private double _ax = 0.0;
public double AX
{
get { return _ax; }
set { _ax = value; OnPropertyChanged("AX"); }
}
// AY
private double _ay = 0.0;
public double AY
{
get { return _ay; }
set { _ay = value; OnPropertyChanged("AY"); }
}
// BX
private double _bx = 0.0;
public double BX
{
get { return _bx; }
set { _bx = value; OnPropertyChanged("BX"); }
}
// BY
private double _by = 0.0;
public double BY
{
get { return _by; }
set { _by = value; OnPropertyChanged("BY"); }
}
#endregion Dependency Properties
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion PropertyChanged
}
}