wpfbindingnotificationsdependency-propertiesdependencyobject

WPF DependencyProperty chain notification


im exploring WPF world, i find a great example on the web about how to use binding on xml

http://www.codeproject.com/Articles/37854/How-to-Perform-WPF-Data-Binding-Using-LINQ-to-XML

Now im trying to extends this example: i want to create a "class in the middle" between the XElement and the UI and bind all togheder in a chain so, if i have a modification into the xml, then i have the property in the middle class updated then the UI updated too.

Here some code:

This is the class that wrap the XElement

public class XElementDataProvider : ObjectDataProvider
{
    public XElementDataProvider()
    {
        ObjectInstance = XElement.Load(@"C:\MyFile.xml");
    }

    private static XElementDataProvider instance;


    public static XElementDataProvider Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new XElementDataProvider();
            }
            return instance;
        }

    }
}

This is the MiddleClass

public class MiddleClass : DependencyObject
{


    XElementDataProvider xElementDataProvider;
    XElement myxml;

    public MiddleClass()
    {
                    //here i get my dataprovider
        xElementDataProvider = XElementDataProvider.Instance;
        myxml = xElementDataProvider.Data as XElement;

                    //i bind my internal collection to the Elements...
        Binding binding = new Binding("Elements[book]")
        {
            Source = myxml,
            Mode = BindingMode.Default//here i cant use TwoWay, give me          //back an exeption
        };


        BindingOperations.SetBinding(this, XBookListProperty, binding);

                    //just to have confirmation of the adding
        myxml.Changed += new EventHandler<XObjectChangeEventArgs (myxml_Changed);

    }

    void myxml_Changed(object sender, XObjectChangeEventArgs e)
    {

    }

            //i use a DependencyProperty to have also a change callback
    public static readonly DependencyProperty XBookListProperty =
        DependencyProperty.Register("XBookList", typeof(IEnumerable),
        typeof(MiddleClass),
        new PropertyMetadata(XBookPropertyChanged)
        );


            //here i have a notification only at start but no when i add a new book
    private static void XBookPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MiddleClass middleClass = d as MiddleClass;
        middleClass.XBookPropertyChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue);
    }

    private void XBookPropertyChanged(IEnumerable old, IEnumerable newValue)
    {

    }
             //this is the propery i finally want to expose to the UI but im not able //to keep updated
    public List<Book> bookList;
    public List<Book> BookList
    {
        get
        {
            return bookList;
        }
        set
        {
            bookList = value;
        }
    }



    //this is my internal list binded to the xml
    private IEnumerable XBookList
    {
        get
        {
            return (IEnumerable)GetValue(XBookListProperty);
        }
        set
        {
            SetValue(XBookListProperty, value);
        }
    }

            //here i try to add a book addind direcly to the xml//i expect a //notification of propery changed...but nothing
    public bool AddBook(string name)
    {

        XElement newWorkSheet = new XElement("Book",
            new XAttribute("Name", name)
            );

        myxml.Add(newWorkSheet);


        return true;
    }

Book is a class thar repersents a book, let say it has only a name propery for now.

The UI class misses but it should bind on public List<Book> BookList and show books names to the user in a ListBox

Enyone knows why i dont recive any notification...or what i have to do to keep the public List<Book> BookList synchronized with private IEnumerable<XBookList>?


Solution

  • OK, after many attempts, the only solution I found is this one:

    to have notifications when something changes in the IEnumerable<XBookList> you need to clear it ad rebind after you modify it.

    In this way you have a first, not used notification, about the clear and then another notification about the new set.

    Then in the handler you can synchronize the new list with the old one.

    public bool AddBook(string name)
    {
    
        XElement newWorkSheet = new XElement("Book",
            new XAttribute("Name", name)
            );
    
        myxml.Add(newWorkSheet);
    
    
        ClearValue(XBookListProperty);
    Binding binding = new Binding("Elements[book]")
        {
            Source = myxml,
            Mode = BindingMode.Default          
        };
        BindingOperations.SetBinding(this, XBookListProperty, binding);
        return true;
    }