В WPF привязки пользовательского объекта inkcanvas
Привет,
Я пытаюсь привязать детскую коллекцию к пользовательским Чернильницам. В этот момент программа связывается с холстом к коду без проблем, но не с другой стороны.
Спасибо за помощь
Петр
Журнал Отладки:
The thread 0x2c88 has exited with code 259 (0x103). 'test_wpf.vshost.exe' (CLR v4.0.30319: test_wpf.vshost.exe): Loaded 'C:\Users\petr.ehler\Documents\Visual Studio 2013\Projects\test_wpf\test_wpf\bin\Debug\test_wpf.exe'. Symbols loaded. 'test_wpf.vshost.exe' (CLR v4.0.30319: test_wpf.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll'. Symbols loaded. 'test_wpf.vshost.exe' (CLR v4.0.30319: test_wpf.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework.Aero\v4.0_4.0.0.0__31bf3856ad364e35\PresentationFramework.Aero.dll'. Symbols loaded. System.Windows.Data Warning: 56 : Created BindingExpression (hash=22226817) for Binding (hash=54181020) System.Windows.Data Warning: 58 : Path: 'BorderItems' System.Windows.Data Warning: 61 : BindingExpression (hash=22226817): Default update trigger resolved to PropertyChanged System.Windows.Data Warning: 62 : BindingExpression (hash=22226817): Attach to test_wpf.MyCanvas.Source (hash=46367191) System.Windows.Data Warning: 67 : BindingExpression (hash=22226817): Resolving source System.Windows.Data Warning: 70 : BindingExpression (hash=22226817): Found data context element: MyCanvas (hash=46367191) (OK) System.Windows.Data Warning: 71 : BindingExpression (hash=22226817): DataContext is null System.Windows.Data Warning: 65 : BindingExpression (hash=22226817): Resolve source deferred System.Windows.Data Warning: 67 : BindingExpression (hash=22226817): Resolving source System.Windows.Data Warning: 70 : BindingExpression (hash=22226817): Found data context element: MyCanvas (hash=46367191) (OK) System.Windows.Data Warning: 78 : BindingExpression (hash=22226817): Activate with root item MainWindow (hash=3528959) System.Windows.Data Warning: 108 : BindingExpression (hash=22226817): At level 0 - for MainWindow.BorderItems found accessor RuntimePropertyInfo(BorderItems) System.Windows.Data Warning: 104 : BindingExpression (hash=22226817): Replace item at level 0 with MainWindow (hash=3528959), using accessor RuntimePropertyInfo(BorderItems) System.Windows.Data Warning: 101 : BindingExpression (hash=22226817): GetValue at level 0 from MainWindow (hash=3528959) using RuntimePropertyInfo(BorderItems): ObservableCollection`1 (hash=55866471 Count=0) System.Windows.Data Warning: 80 : BindingExpression (hash=22226817): TransferValue - got raw value ObservableCollection`1 (hash=55866471 Count=0) System.Windows.Data Warning: 89 : BindingExpression (hash=22226817): TransferValue - using final value ObservableCollection`1 (hash=55866471 Count=0) 'test_wpf.vshost.exe' (CLR v4.0.30319: test_wpf.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework-SystemXmlLinq\v4.0_4.0.0.0__b77a5c561934e089\PresentationFramework-SystemXmlLinq.dll'. Symbols loaded. 'test_wpf.vshost.exe' (CLR v4.0.30319: test_wpf.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework-SystemXml\v4.0_4.0.0.0__b77a5c561934e089\PresentationFramework-SystemXml.dll'. Symbols loaded. 'test_wpf.vshost.exe' (CLR v4.0.30319: test_wpf.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\UIAutomationTypes\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationTypes.dll'. Symbols loaded. System.Windows.Data Warning: 95 : BindingExpression (hash=22226817): Got PropertyChanged event from MainWindow (hash=3528959) System.Windows.Data Warning: 101 : BindingExpression (hash=22226817): GetValue at level 0 from MainWindow (hash=3528959) using RuntimePropertyInfo(BorderItems): ObservableCollection`1 (hash=55866471 Count=1) System.Windows.Data Warning: 80 : BindingExpression (hash=22226817): TransferValue - got raw value ObservableCollection`1 (hash=55866471 Count=1) System.Windows.Data Warning: 89 : BindingExpression (hash=22226817): TransferValue - using final value ObservableCollection`1 (hash=55866471 Count=1) 'test_wpf.vshost.exe' (CLR v4.0.30319: test_wpf.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework-SystemData\v4.0_4.0.0.0__b77a5c561934e089\PresentationFramework-SystemData.dll'. Symbols loaded. System.Windows.Data Warning: 95 : BindingExpression (hash=22226817): Got PropertyChanged event from MainWindow (hash=3528959) System.Windows.Data Warning: 101 : BindingExpression (hash=22226817): GetValue at level 0 from MainWindow (hash=3528959) using RuntimePropertyInfo(BorderItems): ObservableCollection`1 (hash=55866471 Count=1) System.Windows.Data Warning: 80 : BindingExpression (hash=22226817): TransferValue - got raw value ObservableCollection`1 (hash=55866471 Count=1) System.Windows.Data Warning: 89 : BindingExpression (hash=22226817): TransferValue - using final value ObservableCollection`1 (hash=55866471 Count=1) System.Windows.Data Warning: 95 : BindingExpression (hash=22226817): Got PropertyChanged event from MainWindow (hash=3528959) System.Windows.Data Warning: 101 : BindingExpression (hash=22226817): GetValue at level 0 from MainWindow (hash=3528959) using RuntimePropertyInfo(BorderItems): ObservableCollection`1 (hash=55866471 Count=1) System.Windows.Data Warning: 80 : BindingExpression (hash=22226817): TransferValue - got raw value ObservableCollection`1 (hash=55866471 Count=1) System.Windows.Data Warning: 89 : BindingExpression (hash=22226817): TransferValue - using final value ObservableCollection`1 (hash=55866471 Count=1) The thread 0x3784 has exited with code 259 (0x103). The thread 0x3050 has exited with code 259 (0x103). The program '[12308] test_wpf.vshost.exe' has exited with code 0 (0x0).
Что я уже пробовал:
основной класс
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Windows; using System.Windows.Input; namespace test_wpf { public partial class MainWindow : Window, INotifyPropertyChanged { public ObservableCollection<ItemDetail> BorderItems { get; set; } public event PropertyChangedEventHandler PropertyChanged; public MainWindow() { InitializeComponent(); DataContext = this; BorderItems = new ObservableCollection<ItemDetail>(); } private void Button_Click(object sender, RoutedEventArgs e) { if(BorderItems.Count == 0) { return; } BorderItems[0].X = 200; BorderItems[0].Y = 300; BorderItems[0].Width = 200; BorderItems[0].Height = 100; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("BorderItems")); } private void Button_Click_1(object sender, RoutedEventArgs e) { ItemDetail d = new ItemDetail(); d.X = 100; d.Y = 100; d.Width = 100; d.Height = 100; d.Type = "text"; d.Text = "Test "+BorderItems.Count.ToString(); BorderItems.Add(d); if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("BorderItems")); } } }
MyCanvas
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; namespace test_wpf { public class MyCanvas : InkCanvas { //Just a simple INotifyCollectionChanged collection public ObservableCollection<ItemDetail> Source { get; set; } public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(ObservableCollection<ItemDetail>), typeof(MyCanvas), new FrameworkPropertyMetadata(new ObservableCollection<ItemDetail>(), new PropertyChangedCallback(SourceChanged))); //called when a new value is set (through binding for example) protected static void SourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { //gets the instance that changed the "local" value var instance = sender as MyCanvas; //the new collection that will be set ObservableCollection<ItemDetail> newCollection = args.NewValue as ObservableCollection<ItemDetail>; //the previous collection that was set ObservableCollection<ItemDetail> oldCollection = args.OldValue as ObservableCollection<ItemDetail>; if (oldCollection != null) { //removes the CollectionChangedEventHandler from the old collection oldCollection.CollectionChanged -= new NotifyCollectionChangedEventHandler(instance.collection_CollectionChanged); } //clears all the previous children in the collection instance.Children.Clear(); if (newCollection != null) { //adds all the children of the new collection foreach (ItemDetail item in newCollection) { AddControl(item, instance); } //adds a new CollectionChangedEventHandler to the new collection newCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(instance.collection_CollectionChanged); } } //append when an Item in the collection is changed protected void collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { //adds the new items in the children collection foreach (ItemDetail item in e.NewItems) { AddControl(item); } } protected static void AddControl(ItemDetail item, InkCanvas parentControl) { Border border = new Border(); border.DataContext = item; border.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#000000")); border.Width = item.Width; border.Height = item.Height; if(item.Type == "text") { TextBlock tb = new TextBlock(); tb.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF")); tb.FontSize = 25; tb.HorizontalAlignment = HorizontalAlignment.Center; tb.VerticalAlignment = VerticalAlignment.Center; Binding TextBinding = new Binding("Text"); TextBinding.Source = item; TextBinding.Mode = BindingMode.TwoWay; tb.SetBinding(TextBlock.TextProperty, TextBinding); //tb.Text = item.Text; border.Child = tb; } parentControl.Children.Add(border); Binding XBinding = new Binding("X"); XBinding.Source = item; XBinding.Mode = BindingMode.TwoWay; Binding YBinding = new Binding("Y"); YBinding.Source = item; YBinding.Mode = BindingMode.TwoWay; border.SizeChanged += border_SizeChanged; border.SetBinding(InkCanvas.LeftProperty, XBinding); border.SetBinding(InkCanvas.TopProperty, YBinding); } private static void border_SizeChanged(object sender, SizeChangedEventArgs e) { Border border = sender as Border; if (border == null) { throw new ArgumentException("Unexpected object. Expected border"); } var i = border.DataContext; ItemDetail itemDetail = i as ItemDetail; if (itemDetail == null) { throw new ArgumentException("Unexpected object. Expected ItemDetail"); } itemDetail.Width = border.ActualWidth; itemDetail.Height = border.ActualHeight; } protected void AddControl(ItemDetail item) { AddControl(item, this); } static MyCanvas() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCanvas), new FrameworkPropertyMetadata(typeof(MyCanvas))); } public MyCanvas() : base() { } } }
Деталь
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Windows.Controls; namespace test_wpf { public class ItemDetail: INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public int X { get; set; } public int Y { get; set; } public double Width { get; set; } public double Height { get; set; } public string Type { get; set; } public string Text { get; set; } } }
MainClassWPF
<Window x:Class="test_wpf.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:test_wpf" Title="InkCanvasElementSelection" ResizeMode="CanResize" xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase" Height="800" Width="600"> <DockPanel LastChildFill="True"> <StackPanel DockPanel.Dock="Left" Width="200" Orientation="Vertical"> <Line Margin="5"/> <TextBlock>Create new Element</TextBlock> <Button Click="Button_Click_1" Height="20" Content="New"/> <Line Margin="5"/> <TextBlock>Change Element 0</TextBlock> <Button Click="Button_Click" Height="20" Content="Change"/> </StackPanel> <src:MyCanvas Source="{Binding Path=BorderItems, Mode=TwoWay}" Background="AliceBlue" EditingMode="Select"/> </DockPanel> </Window>
Richard Deeming
Проверьте окно "вывод" в Visual Studio на наличие ошибок привязки.