Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WinForms IBindingList Collection Support #182

Closed
bchavez opened this issue Nov 12, 2018 · 11 comments
Closed

WinForms IBindingList Collection Support #182

bchavez opened this issue Nov 12, 2018 · 11 comments
Labels

Comments

@bchavez
Copy link

bchavez commented Nov 12, 2018

Hello,

ReactiveUI has deprecated ReactiveBindingList<T> which had support for IBindingList. The obsolete message reads:

ReactiveList is no longer supported. We suggest replacing
it with DynamicData https://github.com/rolandpheasant/dynamicdata

So I searched here for any type that implements IBindingList and couldn't find anything. Effectively, without some type implementing IBindingList there doesn't seem to be a story for binding collections to WinForms controls such as a ListBox.

I think what we need is a type similar to WPF's ObservableCollectionExtended<T>, but for WinForms like ObservableBindingListExtended<T> that implements IBindingList (or BindingList<T>) that can be used similar to:

this.SourceCache
   .Connect()
   .Bind(this.ObservableBindingListExtended)
   .Subscribe();

Let me know your thoughts.

Thanks,
Brian

@glennawatson
Copy link
Member

@RolandPheasant You should actually be able to make a ReadOnlyBindableCollection<T> style container and use the Bind(out myList); type syntax.

@RolandPheasant
Copy link
Collaborator

Hi, I agree this needs adding to the lib.

In the meantime there is a sample implementation which you can copy into your project binding list example

@RolandPheasant
Copy link
Collaborator

RolandPheasant commented Nov 12, 2018

The example in the link is for a list, not a cache. I will ensure both list and cache are supported. Also I will post a cache example later so you can test it before release.

@RolandPheasant
Copy link
Collaborator

I have added Bind() support for binding list for both cache and list parts of the system.

What I have not done is to support ToObservableChangeSet() from BindingList.

Also the suggestion by @glennawatson to create a read-only binding list and bind using an out param is not implemented. I will probably do it in the near future.

@bchavez since this is new functionality I could deploy to Nuget without breaking any code so I will do this very soon. However it would be good if you can download the packages from here AppVeyor Build v99.99.99.2523-branches and test first

@RolandPheasant
Copy link
Collaborator

@bchavez I've merge it in, so you need to download v6.7.0 from the AppVeyor artefacts

@bchavez
Copy link
Author

bchavez commented Nov 12, 2018

Hey @RolandPheasant ,

I think it works!

screen_2368

Thanks again so much for your help @RolandPheasant and @glennawatson . Such amazing work! I really appreciate it.

BTW, here is my ViewModel code in case anyone is interested:

public class Account
{
   public int Id { get; set; }
   public string Name { get; set; }
   public string Number { get; set; }
}

public class MainViewModel : ReactiveObject
{
   public MainViewModel()
   {
      this.Accounts = new BindingList<Account>();
      this.AccountCache = new SourceCache<Account, int>(f => f.Id);


      this.AccountCache.Connect()
         .Bind(this.Accounts)
         .Subscribe();

      var hasAccounts = this.AccountCache.CountChanged
         .Select(x => x > 0);
      
      this.AddAccount = ReactiveCommand2.Create(AddAccountImpl, Observable.Return(true));
      this.RemoveAccount = ReactiveCommand2.Create(RemoveAccountImpl, hasAccounts);
   }

   private Account selectedAccount;
   public Account SelectedAccount
   {
      get => selectedAccount;
      set => this.RaiseAndSetIfChanged(ref selectedAccount, value);
   }

   public ReactiveCommand2<Unit, Unit> AddAccount { get; }
   public ReactiveCommand2<Unit, Unit> RemoveAccount { get; }

   public BindingList<Account> Accounts { get; }

   public SourceCache<Account, int> AccountCache { get; }

   private void RemoveAccountImpl()
   {
      if( this.selectedAccount != null )
         this.AccountCache.Remove(this.selectedAccount);
   }

   private int nextId = 0;

   private void AddAccountImpl()
   {
      var id = nextId++;
      var a = new Account
         {
            Id = id,
            Name = $"Account {id}",
            Number = "12345"
         };

      this.AccountCache.AddOrUpdate(a);
   }
}

I hope I'm using the new IBindingList feature correctly. I'm very noobish with ReactiveUI; I'm still learning! 😢

@RolandPheasant
Copy link
Collaborator

That's great to see. I will deploy it now.

Are you on slack? There is an active community with channels for Rx, RxUI and DynamicData. It is a great place to ask questions Link to join slack

@RolandPheasant
Copy link
Collaborator

On second thoughts it is late here and I need to update the release notes before I deploy. Will do it in the next couple days.

@bchavez
Copy link
Author

bchavez commented Nov 12, 2018

@RolandPheasant , yep! Just joined slack yesterday my username is @bchavez. It was @glennawatson on slack who suggested I raise the issue about IBindingList here. :)

Again, thanks for all the help and support! ❤️ I have a long road ahead to learn all the ins and outs, but this IBindingList was a major blocker that's now been unblocked. :)

@RolandPheasant
Copy link
Collaborator

Feel free to ask any questions and report any issues

@RolandPheasant
Copy link
Collaborator

Fixed by PR #183

@lock lock bot added the outdated label Jul 9, 2019
@lock lock bot locked and limited conversation to collaborators Jul 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants