BusyIndicator override the Command CanExecute from Button

9 posts, 0 answers
  1. Bruno
    Bruno avatar
    54 posts
    Member since:
    Jul 2012

    Posted 04 Apr 2012 Link to this post

    Hi Telerik Team

    In our project, we have a search (wcf service) where the user can export the result from this search. The Export of this result is handled with a RadButton and Command. (Export is only possible if a result exist!)
    During the search, we display a BusyIndicator. When the search is finished and no results were found, the Export Button is still enabled, although the CanExecute of the Export Command is false!

    Sample:
    First, the two Buttons are disabled (because the Search-Result is null).
    When you search for 'test', the Buttons becomes enabled (because 3 Results were found).
    Now, when you search for 'testx', only the Button outside of the BusyIndicator becomes disabled. (Search-Result is null). The Button inside the BusyIndicator still is enabled!

    Sample code:
    <UserControl x:Class="SilverlightApplication3.BusyCommandTest"
        mc:Ignorable="d"
        d:DesignHeight="500" d:DesignWidth="500">
        
       <telerik:RadDockPanel>
          <telerik:RadButton telerik:RadDockPanel.Dock="Top" Content="Command (outside of RadBusyIndicator)" Command="{Binding ExportResultCommand}" Margin="30,30,30,10"/>
          <telerik:RadBusyIndicator IsIndeterminate="True" IsBusy="{Binding IsBusy}" BusyContent="Going on...">
     
             <telerik:RadDockPanel>
                <telerik:RadButton telerik:RadDockPanel.Dock="Top" Content="Command (inside of RadBusyIndicator)" Command="{Binding ExportResultCommand}" Margin="30,0,30,30"/>
                <StackPanel Orientation="Horizontal" telerik:RadDockPanel.Dock="Top" Margin="30">
                   <TextBox Text="{Binding SearchTerm, Mode=TwoWay}" Width="300"/>
                   <telerik:RadButton Content="Search" Command="{Binding SearchCommand}"/>
                   <telerik:RadButton Content="InvalidateCanExecute" Command="{Binding InvalidateCommand}"/>
                </StackPanel>
                <telerik:RadGridView ItemsSource="{Binding ResultList}" Margin="30"/>
             </telerik:RadDockPanel>
     
          </telerik:RadBusyIndicator>
     
       </telerik:RadDockPanel>
    </UserControl>


    ViewModel (DataContext of UserControl)
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Input;
    using Telerik.Windows.Controls;
     
    namespace SilverlightApplication3
    {
       public class BusyCommandViewModel : ViewModelBase
       {
          public BusyCommandViewModel()
          {
             this.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(BusyCommandViewModel_PropertyChanged);
          }
     
          void BusyCommandViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
          {
             if (e.PropertyName == "ResultList")
             {
                ExportResultCommand.InvalidateCanExecute();
             }
          }
     
          private bool isBusy;
          public bool IsBusy
          {
             get { return isBusy; }
             set
             {
                isBusy = value;
                this.OnPropertyChanged("IsBusy");
             }
          }
          private string searchTerm;
          public string SearchTerm
          {
             get { return searchTerm; }
             set
             {
                searchTerm = value;
                this.OnPropertyChanged("SearchTerm");
             }
          }
     
          private ICommand searchCommand;
          public ICommand SearchCommand
          {
             get
             {
                if (searchCommand == null)
                {
                   searchCommand = new DelegateCommand(this.DoSearch);
                }
                return searchCommand;
             }
          }
     
          private void DoSearch(object param)
          {
             this.IsBusy = true;
     
             // Backgroundworker to Simulate WCF Service Search
             BackgroundWorker worker = new BackgroundWorker();
             worker.DoWork += (sender, e) =>
             {
                Thread.SpinWait(100000000);
             };
             worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
             worker.RunWorkerAsync();
          }
     
          void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
          {
             if (this.SearchTerm == "test")
             {
                ObservableCollection<TestObject> tempList = new ObservableCollection<TestObject>();
                tempList.Add(new TestObject("Entry1.1", "Entry1.2"));
                tempList.Add(new TestObject("Entry2.1", "Entry2.2"));
                tempList.Add(new TestObject("Entry3.1", "Entry3.2"));
                this.ResultList = tempList;
             }
             else
             {
                this.ResultList = null;
             }
     
             this.IsBusy = false;
          }
     
          private DelegateCommand exportResultCommand;
          public DelegateCommand ExportResultCommand
          {
             get
             {
                if (exportResultCommand == null)
                {
                   exportResultCommand = new DelegateCommand(this.DoExportResult, this.CanExportResult);
                }
                return exportResultCommand;
             }
          }
     
          private bool CanExportResult(object p)
          {
             bool canExport = this.ResultList != null && this.ResultList.Count > 0;
             return canExport;
          }
     
          private void DoExportResult(object p)
          {
             // Action to Export
          }
     
          private ICommand invalidateCommand;
          public ICommand InvalidateCommand
          {
             get
             {
                if (invalidateCommand == null)
                {
                   invalidateCommand = new DelegateCommand(this.DoInvalidate);
                }
                return invalidateCommand;
             }
          }
     
          private void DoInvalidate(object param)
          {
             ExportResultCommand.InvalidateCanExecute();
          }
     
     
          private ObservableCollection<TestObject> resultList;
          public ObservableCollection<TestObject> ResultList
          {
             get { return resultList; }
             set
             {
                resultList = value;
                this.OnPropertyChanged("ResultList");
             }
          }
       }
     
       public class TestObject
       {
          public TestObject(string column1, string column2)
          {
             this.Column1 = column1;
             this.Column2 = column2;
          }
     
          public string Column1 { get; set; }
          public string Column2 { get; set; }
       }
    }

    Thank you.
  2. Yana
    Admin
    Yana avatar
    4554 posts

    Posted 09 Apr 2012 Link to this post

    Hello Bruno,

    Thank you for reporting this issue, we will research it in more details.  I will write here as soon as we have a result.

    Kind regards,
    Yana
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. DevCraft banner
  4. Ivo
    Admin
    Ivo avatar
    390 posts

    Posted 10 Apr 2012 Link to this post

    Hello Bruno,

    We have investigated this and an easy workaround for it. You can bind to the IsBusyIndicatorVisible property and you can invalidate the command when the property into your ViewModel changes. Here is sample code:
    <telerik:RadBusyIndicator IsBusyIndicationVisible="{Binding IsBusyIndicatorVisible, Mode=TwoWay}"
                                      IsBusy="{Binding IsBusy, Mode=TwoWay}"
                                      BusyContent="Going on...">
    ....

    private bool _IsBusyIndicatorVisible;
    public bool IsBusyIndicatorVisible
    {
        get
        {
            return this._IsBusyIndicatorVisible;
        }
        set
        {
            if (value != this._IsBusyIndicatorVisible)
            {
                this._IsBusyIndicatorVisible = value;
                this.OnPropertyChanged("IsBusyIndicatorVisible");
                this.exportResultCommand.InvalidateCanExecute();
            }
        }
    }

    All the best, Ivo
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  5. Bruno
    Bruno avatar
    54 posts
    Member since:
    Jul 2012

    Posted 18 Apr 2012 Link to this post

    Hi Ivo,

    Thank you for the workaround.
    In our Architecture with base classes etc., it isn't (easy) possible to implement this workaround.
    Is the Bug scheduled for fixing?

    Thank you and kind regards,
    Bruno
  6. Ivo
    Admin
    Ivo avatar
    390 posts

    Posted 23 Apr 2012 Link to this post

    Hi Bruno,

    I believe this issue cannot be fixed at our side for the present. We understand this may not be easy to workaround into your application, but it seems this is the only way to get it working.

    All the best, Ivo
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  7. Bruno
    Bruno avatar
    54 posts
    Member since:
    Jul 2012

    Posted 24 Apr 2012 Link to this post

    Hi Ivo,

    Thank you for your answer.
    That aren't good news.
    Additional information to this bug: With the Standard Silverlight Button (not Telerik RadButton) and the RelayCommand (from MVVM Light Toolkit, not Telerik DelegateCommand), it works! Maybe this could help for fixing the bug.

    Kind regards,
    Bruno

  8. Ivo
    Admin
    Ivo avatar
    390 posts

    Posted 26 Apr 2012 Link to this post

    Hi Bruno,

    Thank you for the additional information.

    All the best, Ivo
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  9. Rodro
    Rodro avatar
    9 posts
    Member since:
    Jun 2012

    Posted 04 Jun 2012 Link to this post

    Hi,

    I have identical problems with version 2012 Q1 SP1.
    It looks like the RadBusyIndicator, besides displaying the busy overlay which already prevents overlayed controls to be clicked, also set IsEnabled="False" (and back to True) on the ContentControl which hosts the covered visual tree. This somehow interfere with the logic of buttons, which update their IsEnabled property based on their Command binding. Which is weird! A Dependency Property set at an inner level should always override whatever value is set at an outer level.

    Anyway, a workaround is to get rid of any fiddling with that property in the BusyIndicator template.
    In my tests the overlay was enough to prevent any action on the proteced parts while busy.

    But I don't know for sure if there is any reason for actually disabling the control...

    -Rodrigo-
  10. Bruno
    Bruno avatar
    54 posts
    Member since:
    Jul 2012

    Posted 19 Jun 2012 Link to this post

    Hi Rodrigo

    Thank you for your reply. Your workaround works for me like a charme!
Back to Top
DevCraft banner