Databinding the IsBackstageOpen property does not have any effect

12 posts, 1 answers
  1. ITC
    ITC avatar
    19 posts
    Member since:
    Nov 2010

    Posted 08 Dec 2011 Link to this post

    Hi

    I would like to control the visibility of the backstage component via my viewmodel through databinding, see below.

    IsBackstageOpen="{Binding BackstageIsOpen}"

    Although I get no errors, the ribbon is not responding to changes in my property value. (I am notifying the property change).

    Any ideas?
  2. Viktor Tsvetkov
    Admin
    Viktor Tsvetkov avatar
    382 posts

    Posted 08 Dec 2011 Link to this post

    Hi Dirk,

    Could you please try setting Mode="TwoWay" in the binding expression and tell me if it works for you?

    Kind regards,
    Viktor Tsvetkov
    the Telerik team

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

  3. UI for WPF is Visual Studio 2017 Ready
  4. ITC
    ITC avatar
    19 posts
    Member since:
    Nov 2010

    Posted 08 Dec 2011 Link to this post

    Thanks it solves 99% of the problem - the backstage is responding to me closing it from the viewmodel.

    The last remaining issue is that I would like the application to start with the Backstage open. Usually you would set it in the XAML and all would be well.

    Because I'm using databinding I set my BackstageIsOpen property to true in the constructor of my viewmodel, but the backstage does not respond.
  5. ITC
    ITC avatar
    19 posts
    Member since:
    Nov 2010

    Posted 08 Dec 2011 Link to this post

    After some more testing it seems that the IsBackStateOpen property only responds to "False" values if set through databinding. I am unable to make the backstage appear from the viewmodel at any time.
  6. Viktor Tsvetkov
    Admin
    Viktor Tsvetkov avatar
    382 posts

    Posted 08 Dec 2011 Link to this post

    Hello Dirk,

    Could you please examine the attached sample project and tell me if it works for you?

    Best wishes,
    Viktor Tsvetkov
    the Telerik team

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

  7. ITC
    ITC avatar
    19 posts
    Member since:
    Nov 2010

    Posted 08 Dec 2011 Link to this post

    Hi Viktor

    Your sample works, but I have tracked down the problem. I am executing code using Task.Factory.StartNew and then setting the property thereafter. When I do that in your sample it fails as well.

    How can I upload a sample to you? The attach file won't allow my zipfile to be uploaded.
  8. ITC
    ITC avatar
    19 posts
    Member since:
    Nov 2010

    Posted 08 Dec 2011 Link to this post

    Hi Viktor

    Make the following changes to the code behind of your sample

    /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
     
                (this.DataContext as MainViewModel).IsBackstageOpen = true;
            }
     
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                var dataContext = this.DataContext as MainViewModel;
                dataContext.DoLongRunningProcess();
            }
        }
     
        public class MainViewModel : ViewModelBase
        {
            private bool isBackstageOpen;
     
            private bool isBusy;
     
            public bool IsBackstageOpen
            {
                get
                {
                    return isBackstageOpen;
                }
                set
                {
                    isBackstageOpen = value;
                    OnPropertyChanged("IsBackstageOpen");
                }
            }
     
            public bool IsBusy
            {
                get { return this.isBusy; }
                set { this.isBusy = value;
                    OnPropertyChanged(() => this.IsBusy);
                }
            }
             
     
            public void DoLongRunningProcess()
            {
                this.IsBusy = true;
     
                this.IsBackstageOpen = !this.IsBackstageOpen;
     
                var task = Task.Factory.StartNew(() => Thread.Sleep(1000));
     
                Task.WaitAll(task);
     
                this.IsBusy = false;
                this.IsBackstageOpen = !this.IsBackstageOpen;
     
            }
        }

    then change your XAML to wrap the stackpanel in a IsBusyIndicator as follows

    <telerik:RadBusyIndicator IsBusy="{Binding IsBusy}" >
            <StackPanel>
                <Button Content="Click" Click="Button_Click" />
                <telerik:RadRibbonView IsBackstageOpen="{Binding IsBackstageOpen, Mode=TwoWay}">
                    <telerik:RadRibbonTab Header="Tab" />
                    <telerik:RadRibbonTab Header="Tab" />
                    <telerik:RadRibbonTab Header="Tab" />
                    <telerik:RadRibbonView.Backstage>
                        <telerik:RadRibbonBackstage>
                            <telerik:RadRibbonBackstageItem Header="Item" />
                            <telerik:RadRibbonBackstageItem Header="Item" />
                            <telerik:RadRibbonBackstageItem Header="Item" />
                        </telerik:RadRibbonBackstage>
                    </telerik:RadRibbonView.Backstage>
                </telerik:RadRibbonView>
            </StackPanel>
        </telerik:RadBusyIndicator>

    You will notice two bugs.

    1. The backstage no longer responds to changes.
    2. The IsBusyIndicator doesn't show up


  9. ITC
    ITC avatar
    19 posts
    Member since:
    Nov 2010

    Posted 12 Dec 2011 Link to this post

    Hi

    Have you been able to test the code I posted?
  10. Viktor Tsvetkov
    Admin
    Viktor Tsvetkov avatar
    382 posts

    Posted 13 Dec 2011 Link to this post

    Hi Dirk,

    Everything is working as expected in your code. The IsBackstageOpen responds to changes, but you cannot notice them, because if you remove the Thread.Sleep method they will happen too fast and if you leave the method it freezes the UI, so nothing can happen (same with the RadBusyIndicator), so you can try your sample with some code which doesn't freeze the UI (i.e. some calculations in a background thread).

    Regards,
    Viktor Tsvetkov
    the Telerik team

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

  11. ITC
    ITC avatar
    19 posts
    Member since:
    Nov 2010

    Posted 13 Dec 2011 Link to this post

    Hi Viktor

    In my real code I am running calculations that don't affect the UI.

    Correct me if I'm wrong, but as I understand it. My Thread.Sleep is running in a background thread. Therefore the UI should not be blocking and the backstage should respond to changes made to its properties.

    I have commented the code as I understand it. The question is whether the Task.WaitAll is blocking the UI thread from updating its status...

    publicvoidDoLongRunningProcess()
            {
                // I am setting the IsBusy to true but don't expect anything to be visible since I am still busy on the calling thread.
                this.IsBusy = true;
                // I am changing the Backstage open stage but don't expect any change since the UI thread is still locked.
                this.IsBackstageOpen = !this.IsBackstageOpen;
                // I am now sleeping on a background thread which should not lock the UI thread. I am expecting the UI to refresh itself from here on.
                var task = Task.Factory.StartNew(() => Thread.Sleep(1000));
                // The code should now wait for the sleep to finish. This might be blocking code...
                Task.WaitAll(task);
                // We are done with the long running process and we reset the busy indicator etc.
                this.IsBusy = false;
                this.IsBackstageOpen = !this.IsBackstageOpen;
      
            }
  12. Answer
    Viktor Tsvetkov
    Admin
    Viktor Tsvetkov avatar
    382 posts

    Posted 13 Dec 2011 Link to this post

    Hello Dirk,

    Excuse me for my last post, I was not clear enough. I meant that the action that is being performed (Thread.Sleep) will block the UI, because of the WaitAll method which actually waits for the action to finish. You can set initially the IsBcakstageOpen property to be false, remove the calling of WaitAll method and you will see that for a fraction of a second the backstage is opened and then closed again (this means that it continues to reflect to changes made from the ViewModel).

    Kind regards,
    Viktor Tsvetkov
    the Telerik team

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

  13. ITC
    ITC avatar
    19 posts
    Member since:
    Nov 2010

    Posted 13 Dec 2011 Link to this post

    Hi Viktor

    Thanks for bearing with me. Based on your feedback I was able to get the correct behavior by making use of the synchronization context as follows:

    this.IsBusy = true;
     
    this.IsBackstageOpen = !this.IsBackstageOpen;
     
    var uiContext = TaskScheduler.FromCurrentSynchronizationContext();
     
    Task.Factory.StartNew(() => Thread.Sleep(1000)).ContinueWith(t =>
                            {
                                this.IsBusy = false;
                                this.IsBackstageOpen = !this.IsBackstageOpen;
                            }, uiContext);
Back to Top
UI for WPF is Visual Studio 2017 Ready