0

I don't think I am even asking this right but here it goes. I have a .NET CF app that displays a datagrid of info. This app is connected by TCP Sockets to a Central Server that will periodically broadcast out data.

How do I get my datagrid on my ShellForm to update. Feels wrong to have a reference to my ShellForm in my DAL where the Socket stuff is happening.

Would I use a Delegate or Async Callback? Just looking for a little guidance. Thanks!

Refracted Paladin
  • 12,096
  • 33
  • 123
  • 233

2 Answers2

2

The DAL can just publish an Event, and then the GUI can subscribe to it.
The reference (and dependency) will be from the GUI to the DAL.

Watch your thread-safety as well.

Community
  • 1
  • 1
H H
  • 263,252
  • 30
  • 330
  • 514
  • I can just make up my own Event? Thanks! I'll Google around for that. Any reason the Compact Framework will make this more difficult? That has been my experience so far is why I ask. Hard to find info on CF specifically but if I don't need to then all the better. – Refracted Paladin Feb 12 '14 at 19:53
  • CF is just a little old and unpopular. Events should work as normal though. I'll add a link. – H H Feb 12 '14 at 19:54
  • Thanks, I think this pretty much answers it. I'm having trouble but I think it's related to my DAL being `static` in this case. It's all just for sending various Socket writes. Anyway, implemented this as a Static Event but when it goes to update the UI I get a `System.NotSupportedException: Control.Invoke must be used...` – Refracted Paladin Feb 12 '14 at 20:30
  • Yes, you need to use Control.Invoke as usual. – H H Feb 12 '14 at 20:33
  • If only I knew what "as usual" was... :) I'll keep looking around. Thanks for all the help! – Refracted Paladin Feb 12 '14 at 20:39
  • The TCP data comes in on another thread, collect and process it and then use Control.Invoke to introduce it to the GUI. Plenty of questions on SO already (cross-thread exception). – H H Feb 13 '14 at 07:57
  • See here for on how to update GUI from background thread: http://www.hjgode.de/wp/2010/06/01/mobile-development-easy-to-use-background-thread-with-gui-update/ (this my aricle with the most hits). – josef Feb 14 '14 at 05:21
2

I'd suggest that your UI shouldn't know anything about your DAL at all. What I'd do for this would be to create an intermediate "presenter" class that watches the DAL and then can notify the UI, either via an event, callback or whatever.

I would most likely create a presenter class that implements INotifyPropertyChanged, which would allow you to directly watch the event or to data bind to the property that you're using to fill your grid. The presenter would also handle marshaling to the UI context, so neither the UI or the DAL would have to worry about it.

Some sort-of pseudo code might look like this. Bear in mind I have all sorts of infrastructure bits in my code, so this is not likely to just compile, but it should give you a flavor of how I'd attack the problem.

class PointPresenter : INotifyPropertyChanged
{
    private IDataService DAL { get; set; }

    protected Control EventInvoker { get; private set; }

    public PointPresenter()
    {
        // get your DAL reference however you'd like
        DAL = RootWorkItem.Services.Get<IDataService>();
        EventInvoker = new Control();
        // this is required to force the EE to actually create the 
        // control's Window handle
        var h = EventInvoker.Handle;
    }

    protected void RaisePropertyChanged(string propertyName)
    {
        try
        {
            if (m_disposed) return;

            EventInvoker.BeginInvokeIfRequired(t =>
            {
                try
                {
                    PropertyChanged.Fire(this, propertyName);

                }
                catch (Exception e)
                {
                    Debug.WriteLine(e);
                }
            });
        }
        catch (ObjectDisposedException)
        {
            // if the Form to which we're sending a message is disposed, 
            // this gets thrown but can safely be ignored
        }
        catch (Exception ex)
        {
            // TODO: log this
        }
    }

    public int MyDataValue
    {
        get { return DAL.Data; }
        set
        {
            if (value == MyDataValue) return;
            DAL.Data = value;
            RaisePropertyChanged("MyDataValue");
        }
    }
}
ctacke
  • 66,480
  • 18
  • 94
  • 155
  • I'd completely disagree. In fact a beginner is the one who *needs* to see better architecture than things like direct DAL access in the designer-generated UI code that you see in every book and tutorial, because that is just flat out bad code and the quicker they break that habit, the better. – ctacke Feb 17 '14 at 23:18