3

I'm having a hard time to decouple two classes.

I have my code behind (will call it "class A") that I use to tweak the interface (defined in xaml).

Next I have a class B that is only logic. But while the logic is executing I have to update the UI.

My problem is that I can't "return" from the class B back to A to update the UI because B has not finished working. And I can't give the view itself to modifiy to B because it would couple A and B.

I suppose that I have to use some interfaces logic but I don't know how.

For example :

Class A
{
     private void OnClickEvent()
     {
         var B = new(B);
         b.work();
     }

     private void UpdateUI()
     {
        ...
     }
}


Class B
{
    public void work()
    {
        while (...)
        {
             ...
             //Here, how to call A.UpdateUI() ?
             ...
        }
    }
}

Thanks !

12
  • 1
    What you're talking about is performing an asynchronous call to another method. You want work to be running in the background while you keep calling UpdateUI.
    – Neil
    Jan 10, 2018 at 14:43
  • the code executed inside the B.work() in non blocant. So I don't need it to be called from background :-)
    – Doctor
    Jan 10, 2018 at 14:45
  • So: private void OnClickEvent() { var B = new(B); b.work(); UpdateUI(); }. If work() is taking too long, then yes, you need to call it asynchronously.
    – Neil
    Jan 10, 2018 at 14:50
  • Yeah I see what you mean. But if in B.work() I could just call the right methods from A it would be a lot simpler than returning a lot of differents return codes to know what I should call in A. I don't have only one method to call that belong in A... Do you understand what I mean ?
    – Doctor
    Jan 10, 2018 at 15:03
  • 1
    I'm assuming B is a dependency of A here. That means A calls B, not the other way around. If it is inconvenient for A to call B, then there is a problem with how your code is organized that should be addressed. In other words, if it is correct for A to call B.work(), then make it such that A can also call UpdateUI. Otherwise, make the appropriate changes and get back to me. ;)
    – Neil
    Jan 10, 2018 at 15:06

3 Answers 3

1

You would probably execute work() asynchronously and then use events to signal the changes which might cause the UI to update. The benefit of events is that the event source does not know anything about the subscribers, so you can still keep the business logic (B) decoupled from the view (A).

5
  • I understand what you mean. But it doesn't feel to be the right solution. I would have to pass a hole lot of methods async then... Would'nt it be a little to bulky to have one event for each small UI changes ?
    – Doctor
    Jan 10, 2018 at 15:05
  • @Doctor: What kind of events is it which will cause UI updates?
    – JacquesB
    Jan 10, 2018 at 15:23
  • First, in my code behind (class A) I have some functions that changes a listView's item source. Another one that removes the separators between the items of the list. And finaly, one that updates a label. All thoses are UI related so they belong to class A. Class B now : The work() method goes through data from an API and based on this data, decides to call some or none methods from class A (Well it would if I knew how to call A's methods from B !). For now the all the code is in A... :-)
    – Doctor
    Jan 10, 2018 at 15:31
  • @Doctor - a good solution for async in Wpf projects is using BackgroundWorker class. You should take a look in this. Jan 13, 2018 at 13:11
  • @Emerson Cardoso Interesting indeed. Thx. But my code is not async. The loop is non blocant.
    – Doctor
    Jan 13, 2018 at 18:27
0

Simply introduce an interface:

class A : BUpdateTarget
{
     private void OnClickEvent()
     {
         var B = new(B);
         b.work(this);
     }

     public void UpdateUI()
     {
        ...
     }
}


interface BUpdateTarget
{
    UpdateUI();
}

class B
{
    public void work(BUpdateTarget updateTarget)
    {
        while (...)
        {
             //...
             updateTarget.UpdateUI()
             //...
        }
    }
}
3
  • Thx for your answer. Are you sure that this is the maximum decoupling I can get using interfaces ?
    – Doctor
    Jan 12, 2018 at 13:28
  • @Doctor I have no idea what you mean by "maximum decoupling". And I have fleeting feeling that this is dangerous way of thinking. Code should only be decoupled to the point of supporting current use cases. And nothing more!
    – Euphoric
    Jan 12, 2018 at 14:27
  • I always thought that the logic should not be aware of the UI. So when I asked about the maximum decoupling, what I meant was : Does giving an interface (that represents the UI) to a logic class as parameter is a sufficient separation from the UI and the logic ?
    – Doctor
    Jan 12, 2018 at 21:58
0

It seems to me that your B class represents the logic of some user interface, while the A represents the code-behind class of the same user interface.

If you just can't use MVVM, I would recommend make the B class implement the INotifyPropertyChanged interface, so it can notify the client (the A class) about changes in its state (like updates in a collection, for instance). Once the change occurs, A gets notified, and can do whatever it needs to do.

1
  • Ok thx. I'll look into it ! I always thought that this was only used for MVVM...
    – Doctor
    Jan 15, 2018 at 16:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.