locked
Binding a remotable, "observable" collection to a ListView. RRS feed

  • Question

  • I have a client/server application with serveral remote clients and a server that contains a datasource (db). First, let me set up a test case. Forget the db for now and lets say I have a serializeable object Message:

    [Serializeable]
    public class Message : MarshallByRefObject, INotifyPropertyChanged
    {    
        private string _text;
        public string Text 
        { 
            get { return _text; } 
            set { _text = value; if(ProperyChanged != null) { PropertyChanged(...); } }
        }
    
        //pretend theres several other properties...
    
        [field:NonSerialized()]
        public event PropertyChangedEventHandler PropertyChanged;
    }
    

    and a server-side collection of them, RemoteableBindableCollection. I have a remotable object wrapping the collection, something like:

    public class ServerProxy : MarshalByRefObject
    {
        public RemoteableBindableCollection MessageList { get; set; }
        public ServerProxy() 
        {
            MessageList = new...;
            //add here for demonstration 
            MessageList.Add(...); 
        }
    }
    

    In my WPF test page, I have a ListView plus a button and txtbox to add a new msg:

    BUTTON name=AddMessage Click="AddMessage_Click" Add /BUTTON
    TEXTBOX Name="MessageTextBox" /
    LISTVIEW Name="MessageListView"
        LISTVIEW.VIEW
            GRIDVIEW
                GRIDVIEWCOLUMN DisplayMemberBinding="{Binding Text}" Header="Text" /GRIDVIEWCOLUMN
            /GRIDVIEW
        /LISTVIEW.VIEW
    /LISTVIEW
    
    public partial class TestWindow : Window
    {
        private ServerProxy _server;
        public TestWindow()
        {
            _server = (ServerProxy)Activator.GetObject(typeof(ServerProxy), 
                "tcp://localhost:10000/server");
            MessageListView.ItemSource = MessageList;
        }
        private void AddMessage_Click(...)
        {
            _server.MessageList.Add(new Message(MessageTextBox.Text));
        }
        public RemoteablebindableCollection MessageList { get { return _server.MessageList; } }
    }
    

    Now the goal here is, 2 clients, 1 server running. Client 1 and 2 see the first message in the list. Client 1 adds a new msg via button and both Client's have their ListView's automagically updated.
    Phew, ok. So now the real question. How do you implement RemoteableBindableCollection to enable this?

    It could get large so I'd rather have it derive from MarshallByRefObject so that the [] operator, enumerators etc. return ref's to the contained objects and hopefully only the required data (i.e. the Text property) is serialized to the clients.

    So far the only solution that I have working involves add a function to the page "UpdateMessageList", that resets the binding:

    MessageListView.ItemsSource = MessageList;
    MessageListView.InvalidateProperty(ItemsControl.ItemsSourceProperty);
    This update function is added to an event in the ServerProxy thats fired when a custom collection calls some "SystemChanged" method in the ServerProxy when the collection changes. 

    I've tried dozens of collection implmentations, for example, a few impls. of serializeable ObservableCollection<T>'s. I get serialization exceptions for anything that derives from MarshallByRefObject and INotifyCollectionChanged. Anyone have any ideas? I'd list all the things I've tried, by my time here has run out for now!

     

    Cheers,

     

    Chris

    Friday, April 11, 2008 2:47 PM

Answers

All replies

  • Do you have a strong requirement for marshaling your collections by reference? Have you looked through WCF and DataContractSerializer? Why not to pass the raw xml or xaml data across the boundaries?

    Sunday, April 13, 2008 11:43 AM
  • Enabling property/collection change notification across machine boundaries is not merely have your remoteable objects implement INotifyPropertyChanged or INotifyCollectionChanged interface. You have to  provide a mechanism to publish change notification and subscribe change notification across the machine boundaries, here is several approach to this problem:

    http://www.codeproject.com/KB/IP/remotingandevents.aspx

    http://www.dotnetspider.com/kb/Article565.aspx


    Hope this helps
    Monday, April 14, 2008 7:15 AM