using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
namespace BindingSample
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Test Binding
            View view1 = new View();
            View view2 = new View();
            ViewModel model = new ViewModel();
            ViewModel2 model2 = new ViewModel2();
            TextConverter converter = new TextConverter();
            BindingEngine.SetPropertyBinding(view1, model, "Text", "Value", converter, null);
            BindingEngine.SetPropertyBinding(view1, model, "Value", "Value");
            BindingEngine.SetPropertyBinding(view2, model, "Text", "Value", converter, 2);
            BindingEngine.SetPropertyBinding(view2, model, "Value", "Value");
            BindingEngine.SetPropertyBinding(view2, model2, "Value2", "Value");
            Console.WriteLine("Set Binding to view1 and view2");
            Console.WriteLine("view1 Text = {0} \t Value = {1} \nview2 Text = {2} \t Value = {3} \t Value2 = {4}", view1.Text, view1.Value, view2.Text, view2.Value, view2.Value2);
            model.Value = 1;
            model2.Value = 4;
            Console.WriteLine("\nSet model.Value = 1, model2 = 4");
            Console.WriteLine("view1 Text = {0} \t Value = {1} \nview2 Text = {2} \t Value = {3} \t Value2 = {4}", view1.Text, view1.Value, view2.Text, view2.Value, view2.Value2);
            Console.WriteLine("\nClear binding of view1");
            BindingEngine.ClearPropertyBinding(view1, model, "Text", "Value");
            BindingEngine.ClearPropertyBinding(view1, model, "Value", "Value");
            model.Value = 3;
            Console.WriteLine("\nSet model.Value = 3");
            Console.WriteLine("view1 Text = {0} \t Value = {1} \nview2 Text = {2} \t Value = {3}", view1.Text, view1.Value, view2.Text, view2.Value);
            //2. Test memory leak
            View view3 = new View();
            ViewModel model3 = new ViewModel();
            WeakReference wr = new WeakReference(view3);
            BindingEngine.SetPropertyBinding(view3, model3, "Text", "Value", converter, null);
            BindingEngine.SetPropertyBinding(view3, model3, "Value", "Value");
            Console.WriteLine("\nSet Binding to view3");
            Console.WriteLine("The view3 is alive : {0}", wr.IsAlive);
            view3 = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            Console.WriteLine("Set view3 = null , after GC Collect");
            Console.WriteLine("The view3 is alive : {0}", wr.IsAlive);
            Console.Read();
        }
    }
    public class View
    {
        public string Text { get; set; }
        public int Value { get; set; }
        public int Value2 { get; set; }
    }
    public class ViewModel : INotifyPropertyChanged
    {
        private int _Value = 0;
        public int Value
        {
            get
            {
                return _Value;
            }
            set
            {
                _Value = value;
                NotifyPropertyChanged("Value");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string prop)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
        }
    }
    public class ViewModel2 : INotifyPropertyChanged
    {
        private int _Value = 0;
        public int Value
        {
            get
            {
                return _Value;
            }
            set
            {
                _Value = value;
                NotifyPropertyChanged("Value");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string prop)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
        }
    }
    public class TextConverter : IDataConverter
    {
        public object Convert(object value, object parameter)
        {
            int v = System.Convert.ToInt32(value);
            if (parameter != null)
            {
                v = System.Convert.ToInt32(parameter) + v;
            }
            return string.Format("\"{0}\"", v);
        }
    }
}