ReactiveCommand with combined criteria for CanExecute












1















I have just started with ReactiveUI. I have the following class:



public class MainViewModel : ReactiveObject, IRoutableViewModel 
{
private string shareText;

public ReactiveCollection<SharingAccountViewModel> SelectedAccounts { get; private set; }

public string ShareText
{
get { return shareText; }
set
{
this.RaiseAndSetIfChanged(ref shareText, value);
}
}

public IReactiveCommand ShareCommand { get; private set; }
}


What I would like to do is to be allow the command to execute when the following criteria is true:




  1. The ShareText property is not null or empty

  2. The SelectedAccounts collection contains at least one value


I have tried the following but it does not work as the button which is hooked up to the command never gets enabled:



ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
viewModel => viewModel.SelectedAccounts,
(x, y) => !String.IsNullOrEmpty(x.Value) && y.Value.Count > 0));


If I just check for the ShareText property however, it works fine:



  ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
(x) => !String.IsNullOrEmpty(x.Value)));


I looked at the answer for the question ReactiveUI: Using CanExecute with a ReactiveCommand



Based on that I tried the following:



var accountsSelected = SelectedAccounts.CollectionCountChanged.Select(count => count > 0);
ShareCommand = new ReactiveCommand(accountsSelected);


This is working for the second part of my execution criteria because as soon as items are added or removed from the collection, the button which is hooked up to the command gets enabled or disabled correctly.



My question is how do I now combine that with checking that the ShareText property is not null or empty?



I cannot use the this.WhenAny(..) method anymore as the accountsSelected variable is not a property.



Thanks










share|improve this question





























    1















    I have just started with ReactiveUI. I have the following class:



    public class MainViewModel : ReactiveObject, IRoutableViewModel 
    {
    private string shareText;

    public ReactiveCollection<SharingAccountViewModel> SelectedAccounts { get; private set; }

    public string ShareText
    {
    get { return shareText; }
    set
    {
    this.RaiseAndSetIfChanged(ref shareText, value);
    }
    }

    public IReactiveCommand ShareCommand { get; private set; }
    }


    What I would like to do is to be allow the command to execute when the following criteria is true:




    1. The ShareText property is not null or empty

    2. The SelectedAccounts collection contains at least one value


    I have tried the following but it does not work as the button which is hooked up to the command never gets enabled:



    ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
    viewModel => viewModel.SelectedAccounts,
    (x, y) => !String.IsNullOrEmpty(x.Value) && y.Value.Count > 0));


    If I just check for the ShareText property however, it works fine:



      ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
    (x) => !String.IsNullOrEmpty(x.Value)));


    I looked at the answer for the question ReactiveUI: Using CanExecute with a ReactiveCommand



    Based on that I tried the following:



    var accountsSelected = SelectedAccounts.CollectionCountChanged.Select(count => count > 0);
    ShareCommand = new ReactiveCommand(accountsSelected);


    This is working for the second part of my execution criteria because as soon as items are added or removed from the collection, the button which is hooked up to the command gets enabled or disabled correctly.



    My question is how do I now combine that with checking that the ShareText property is not null or empty?



    I cannot use the this.WhenAny(..) method anymore as the accountsSelected variable is not a property.



    Thanks










    share|improve this question



























      1












      1








      1


      1






      I have just started with ReactiveUI. I have the following class:



      public class MainViewModel : ReactiveObject, IRoutableViewModel 
      {
      private string shareText;

      public ReactiveCollection<SharingAccountViewModel> SelectedAccounts { get; private set; }

      public string ShareText
      {
      get { return shareText; }
      set
      {
      this.RaiseAndSetIfChanged(ref shareText, value);
      }
      }

      public IReactiveCommand ShareCommand { get; private set; }
      }


      What I would like to do is to be allow the command to execute when the following criteria is true:




      1. The ShareText property is not null or empty

      2. The SelectedAccounts collection contains at least one value


      I have tried the following but it does not work as the button which is hooked up to the command never gets enabled:



      ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
      viewModel => viewModel.SelectedAccounts,
      (x, y) => !String.IsNullOrEmpty(x.Value) && y.Value.Count > 0));


      If I just check for the ShareText property however, it works fine:



        ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
      (x) => !String.IsNullOrEmpty(x.Value)));


      I looked at the answer for the question ReactiveUI: Using CanExecute with a ReactiveCommand



      Based on that I tried the following:



      var accountsSelected = SelectedAccounts.CollectionCountChanged.Select(count => count > 0);
      ShareCommand = new ReactiveCommand(accountsSelected);


      This is working for the second part of my execution criteria because as soon as items are added or removed from the collection, the button which is hooked up to the command gets enabled or disabled correctly.



      My question is how do I now combine that with checking that the ShareText property is not null or empty?



      I cannot use the this.WhenAny(..) method anymore as the accountsSelected variable is not a property.



      Thanks










      share|improve this question
















      I have just started with ReactiveUI. I have the following class:



      public class MainViewModel : ReactiveObject, IRoutableViewModel 
      {
      private string shareText;

      public ReactiveCollection<SharingAccountViewModel> SelectedAccounts { get; private set; }

      public string ShareText
      {
      get { return shareText; }
      set
      {
      this.RaiseAndSetIfChanged(ref shareText, value);
      }
      }

      public IReactiveCommand ShareCommand { get; private set; }
      }


      What I would like to do is to be allow the command to execute when the following criteria is true:




      1. The ShareText property is not null or empty

      2. The SelectedAccounts collection contains at least one value


      I have tried the following but it does not work as the button which is hooked up to the command never gets enabled:



      ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
      viewModel => viewModel.SelectedAccounts,
      (x, y) => !String.IsNullOrEmpty(x.Value) && y.Value.Count > 0));


      If I just check for the ShareText property however, it works fine:



        ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
      (x) => !String.IsNullOrEmpty(x.Value)));


      I looked at the answer for the question ReactiveUI: Using CanExecute with a ReactiveCommand



      Based on that I tried the following:



      var accountsSelected = SelectedAccounts.CollectionCountChanged.Select(count => count > 0);
      ShareCommand = new ReactiveCommand(accountsSelected);


      This is working for the second part of my execution criteria because as soon as items are added or removed from the collection, the button which is hooked up to the command gets enabled or disabled correctly.



      My question is how do I now combine that with checking that the ShareText property is not null or empty?



      I cannot use the this.WhenAny(..) method anymore as the accountsSelected variable is not a property.



      Thanks







      c# system.reactive reactiveui






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 1 at 13:17









      Askolein

      1,94011731




      1,94011731










      asked Mar 18 '13 at 10:03









      Jerrie PelserJerrie Pelser

      423714




      423714
























          2 Answers
          2






          active

          oldest

          votes


















          6














          Using WhenAny with an IObservable is a bit tricky. Here's how I would do it:



          var canShare = Observable.CombineLatest(
          this.WhenAnyObservable(x => x.SelectedAccounts.CollectionCountChanged),
          this.WhenAny(x => x.ShareText, x => x.Value),
          (count, text) => count > 0 && !String.IsNullOrWhitespace(text));


          The advantage of WhenAnyObservable here, is that if you decided to reassign SelectedAccounts (i.e. SelectedAccounts = new ReactiveCollection(...);, the above statement would still work, whereas the one above would still be listening to the old collection.






          share|improve this answer
























          • Thank you Paul. I like your solution as it is more compact and slightly easier for me to understand. Trying to get my head around Rx... Loving your work on ReactiveUI btw

            – Jerrie Pelser
            Mar 19 '13 at 4:10





















          1














          I believe that there are different ways to get the expected result and this is just one way.





          var canExecute = this.ObservableForProperty(v => v.ShareText)
          .Select(_ => Unit.Default)
          .Merge(SelectedAccounts.CollectionCountChanged
          .Select(_ => Unit.Default))
          .Select(_ => !String.IsNullOrEmpty(ShareText)
          && SelectedAccounts.Any())
          .StartWith(false);

          ShareCommand = new ReactiveCommand(canExecute);





          share|improve this answer


























          • Works like a charm, thanks!

            – Jerrie Pelser
            Mar 19 '13 at 0:25











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f15474043%2freactivecommand-with-combined-criteria-for-canexecute%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          6














          Using WhenAny with an IObservable is a bit tricky. Here's how I would do it:



          var canShare = Observable.CombineLatest(
          this.WhenAnyObservable(x => x.SelectedAccounts.CollectionCountChanged),
          this.WhenAny(x => x.ShareText, x => x.Value),
          (count, text) => count > 0 && !String.IsNullOrWhitespace(text));


          The advantage of WhenAnyObservable here, is that if you decided to reassign SelectedAccounts (i.e. SelectedAccounts = new ReactiveCollection(...);, the above statement would still work, whereas the one above would still be listening to the old collection.






          share|improve this answer
























          • Thank you Paul. I like your solution as it is more compact and slightly easier for me to understand. Trying to get my head around Rx... Loving your work on ReactiveUI btw

            – Jerrie Pelser
            Mar 19 '13 at 4:10


















          6














          Using WhenAny with an IObservable is a bit tricky. Here's how I would do it:



          var canShare = Observable.CombineLatest(
          this.WhenAnyObservable(x => x.SelectedAccounts.CollectionCountChanged),
          this.WhenAny(x => x.ShareText, x => x.Value),
          (count, text) => count > 0 && !String.IsNullOrWhitespace(text));


          The advantage of WhenAnyObservable here, is that if you decided to reassign SelectedAccounts (i.e. SelectedAccounts = new ReactiveCollection(...);, the above statement would still work, whereas the one above would still be listening to the old collection.






          share|improve this answer
























          • Thank you Paul. I like your solution as it is more compact and slightly easier for me to understand. Trying to get my head around Rx... Loving your work on ReactiveUI btw

            – Jerrie Pelser
            Mar 19 '13 at 4:10
















          6












          6








          6







          Using WhenAny with an IObservable is a bit tricky. Here's how I would do it:



          var canShare = Observable.CombineLatest(
          this.WhenAnyObservable(x => x.SelectedAccounts.CollectionCountChanged),
          this.WhenAny(x => x.ShareText, x => x.Value),
          (count, text) => count > 0 && !String.IsNullOrWhitespace(text));


          The advantage of WhenAnyObservable here, is that if you decided to reassign SelectedAccounts (i.e. SelectedAccounts = new ReactiveCollection(...);, the above statement would still work, whereas the one above would still be listening to the old collection.






          share|improve this answer













          Using WhenAny with an IObservable is a bit tricky. Here's how I would do it:



          var canShare = Observable.CombineLatest(
          this.WhenAnyObservable(x => x.SelectedAccounts.CollectionCountChanged),
          this.WhenAny(x => x.ShareText, x => x.Value),
          (count, text) => count > 0 && !String.IsNullOrWhitespace(text));


          The advantage of WhenAnyObservable here, is that if you decided to reassign SelectedAccounts (i.e. SelectedAccounts = new ReactiveCollection(...);, the above statement would still work, whereas the one above would still be listening to the old collection.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Mar 19 '13 at 1:42









          Paul BettsPaul Betts

          64.7k15116190




          64.7k15116190













          • Thank you Paul. I like your solution as it is more compact and slightly easier for me to understand. Trying to get my head around Rx... Loving your work on ReactiveUI btw

            – Jerrie Pelser
            Mar 19 '13 at 4:10





















          • Thank you Paul. I like your solution as it is more compact and slightly easier for me to understand. Trying to get my head around Rx... Loving your work on ReactiveUI btw

            – Jerrie Pelser
            Mar 19 '13 at 4:10



















          Thank you Paul. I like your solution as it is more compact and slightly easier for me to understand. Trying to get my head around Rx... Loving your work on ReactiveUI btw

          – Jerrie Pelser
          Mar 19 '13 at 4:10







          Thank you Paul. I like your solution as it is more compact and slightly easier for me to understand. Trying to get my head around Rx... Loving your work on ReactiveUI btw

          – Jerrie Pelser
          Mar 19 '13 at 4:10















          1














          I believe that there are different ways to get the expected result and this is just one way.





          var canExecute = this.ObservableForProperty(v => v.ShareText)
          .Select(_ => Unit.Default)
          .Merge(SelectedAccounts.CollectionCountChanged
          .Select(_ => Unit.Default))
          .Select(_ => !String.IsNullOrEmpty(ShareText)
          && SelectedAccounts.Any())
          .StartWith(false);

          ShareCommand = new ReactiveCommand(canExecute);





          share|improve this answer


























          • Works like a charm, thanks!

            – Jerrie Pelser
            Mar 19 '13 at 0:25
















          1














          I believe that there are different ways to get the expected result and this is just one way.





          var canExecute = this.ObservableForProperty(v => v.ShareText)
          .Select(_ => Unit.Default)
          .Merge(SelectedAccounts.CollectionCountChanged
          .Select(_ => Unit.Default))
          .Select(_ => !String.IsNullOrEmpty(ShareText)
          && SelectedAccounts.Any())
          .StartWith(false);

          ShareCommand = new ReactiveCommand(canExecute);





          share|improve this answer


























          • Works like a charm, thanks!

            – Jerrie Pelser
            Mar 19 '13 at 0:25














          1












          1








          1







          I believe that there are different ways to get the expected result and this is just one way.





          var canExecute = this.ObservableForProperty(v => v.ShareText)
          .Select(_ => Unit.Default)
          .Merge(SelectedAccounts.CollectionCountChanged
          .Select(_ => Unit.Default))
          .Select(_ => !String.IsNullOrEmpty(ShareText)
          && SelectedAccounts.Any())
          .StartWith(false);

          ShareCommand = new ReactiveCommand(canExecute);





          share|improve this answer















          I believe that there are different ways to get the expected result and this is just one way.





          var canExecute = this.ObservableForProperty(v => v.ShareText)
          .Select(_ => Unit.Default)
          .Merge(SelectedAccounts.CollectionCountChanged
          .Select(_ => Unit.Default))
          .Select(_ => !String.IsNullOrEmpty(ShareText)
          && SelectedAccounts.Any())
          .StartWith(false);

          ShareCommand = new ReactiveCommand(canExecute);






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 18 '13 at 22:14

























          answered Mar 18 '13 at 21:27









          Doug MitchellDoug Mitchell

          16218




          16218













          • Works like a charm, thanks!

            – Jerrie Pelser
            Mar 19 '13 at 0:25



















          • Works like a charm, thanks!

            – Jerrie Pelser
            Mar 19 '13 at 0:25

















          Works like a charm, thanks!

          – Jerrie Pelser
          Mar 19 '13 at 0:25





          Works like a charm, thanks!

          – Jerrie Pelser
          Mar 19 '13 at 0:25


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f15474043%2freactivecommand-with-combined-criteria-for-canexecute%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Monofisismo

          Angular Downloading a file using contenturl with Basic Authentication

          Olmecas