Click here to Skip to main content
15,887,434 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi,
I am trying to Bind Children collection to Custom Inkcanvas. In this moment program binds from canvas to code without problem, but not othreside.
Thank you for help
Petr


Debug Log:
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).


What I have tried:

Main Class
C#
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
C#
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()
        {

        }
    }
}


Item detail
C#
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
XML
<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>
Posted
Updated 17-Apr-17 22:06pm
v2
Comments
Richard Deeming 6-Apr-17 12:48pm    
Check the "Output" window in Visual Studio for binding errors.

1 solution

Hi,
solution was quite simple. Inkcanvas did not know about changes in ItemDetail class. The class ItemDetail was not observable. Just update class like

C#
public class ItemDetail: INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private int _x;
        private int _y;
        private double _width;
        private double _height;
        private string _type;
        private string _text;

        public int X {
            get { return _x; }
            set { _x = value; NotifyPropertyChanged("X"); }
        }

        public int Y
        {
            get { return _y; }
            set { _y = value; NotifyPropertyChanged("Y"); }
        }

        public double Width
        {
            get { return _width; }
            set { _width = value; NotifyPropertyChanged("Width"); }
        }

        public double Height
        {
            get { return _height; }
            set { _height = value; NotifyPropertyChanged("Height"); }
        }

        public string Type
        {
            get { return _type; }
            set { _type = value; NotifyPropertyChanged("Type"); }
        }
        public string Text
        {
            get { return _text; }
            set { _text = value; NotifyPropertyChanged("Text"); }
        }
        
    }


and the code is functional.

Petr
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900