9

My project is based on the MVVM pattern.

I have built a tree view that shows my file system. Each folder has a checkbox for selecting the current folder. The selection process is taking some time so, while the operation runs, there is a button which is disabled and at the end of the operation I`m enabling the button.

My problem is that when the button gets "disabled" I see it immediately. However, when the button is going back to the enabled mode I must do some action (like mouse click) to see the button enabled.

How can I make sure that the UI will be updated immediately after the button is enabled?

These are my buttons:

<Button Content="&lt;- Back" Margin="5,0,5,0" Width="80" Height="25"
        IsEnabled="{Binding CanMoveToPreviousPage, UpdateSourceTrigger=PropertyChanged}" 
        Command="{Binding Path=NavigateBackCommand, IsAsync=True}" />

<Button Content="{Binding ButtonNextCaption}" Margin="5,0,5,0" Width="80" Height="25"
        IsEnabled="{Binding CanMoveToNextPage, UpdateSourceTrigger=PropertyChanged}" 
        Command="{Binding Path=NavigateNextCommand, IsAsync=True}" />

In my ViewModel I added this code:

public bool CanMoveToNextPage
{
    get
    {
        return this.CurrentPage != null && this.CurrentPage.CanMoveNext;
    }
    set
    {
        if (CurrentPage != null)
        {
            this.CurrentPage.CanMoveNext = value;
            OnPropertyChanged("CanMoveToNextPage");
        }
    }
}

public bool CanMoveToPreviousPage
{
    get { return 0 < this.CurrentPageIndex && CurrentPage.CanMoveBack; }
    set
    {
        if (CurrentPage != null)
        {
            this.CurrentPage.CanMoveBack = value;
            OnPropertyChanged("CanMoveToPreviousPage");
        }
    }
}

The UI update happens just after I execute a mouse click or any keystroke.

This is the code of the action that is disabling and enabling the buttons:

void bg_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
    DecrementDoneCounter();
    if (ThreadSafeCouner == 0)//means all bg workers are done
    {
        UIlimitation(true);
    }
}

private int ThreadSafeCouner; // check how many bgworkers run
public void IncrementDoneCounter() { Interlocked.Increment(ref ThreadSafeCouner); }
public void DecrementDoneCounter() { Interlocked.Decrement(ref ThreadSafeCouner); }


void bg_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    IncrementDoneCounter();
    UIlimitation(false);
    ((bgArguments)e.Argument).SelectedDirectory.CanSelected = false;
    MarkItems(((bgArguments)e.Argument).SelectedDirectory, ((bgArguments)e.Argument).IsSelect);
    ((bgArguments)e.Argument).FreeWorkerAllocation();
    ((bgArguments)e.Argument).SelectedDirectory.CanSelected = true;
}

//this is the enabling action which execute the propeties setters at the upper part of this post
private static void UIlimitation(bool limit)
{
    MainWindowViewModel.Instance.CanMoveToNextPage = limit;
    MainWindowViewModel.Instance.CanMoveToPreviousPage = limit;
}

What can I do?

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Ofir
  • 5,049
  • 5
  • 36
  • 61
  • 1
    try this.UpdateLayout() or ButtonsParent.UpdateLayout() – Florian Gl Oct 02 '12 at 13:53
  • When your operation is done are you raising the `OnPropertyChanged` event for your concerned properties responsible for enabling/disabling the button? – Rohit Vats Oct 02 '12 at 15:11
  • When i done I`m changing the enabled property but Set{...} and the Set{} include the OnPropertyChanged event. When I try to debug everything works perfevt and the button get enabled without click. I can figure it out what is the problem – Ofir Oct 02 '12 at 18:54
  • I added the code when i raise the event. Thanks for your help – Ofir Oct 02 '12 at 19:26

3 Answers3

6

You can adjust on your control Binding mode TwoWay and define triggers with PropertyChanged

{Binding ElementName=.., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
Aghilas Yakoub
  • 28,516
  • 5
  • 46
  • 51
4

OK I found a solution.
I tried everything without success and eventually I found this thread: Refresh WPF Command

I have used CommandManager.InvalidateRequerySuggested()

And its works.

Thanks for your help

Community
  • 1
  • 1
Ofir
  • 5,049
  • 5
  • 36
  • 61
3

Here's a code example of how you might set up your ViewModel with the INotifyPropertyChanged method of sending messages to update the UI:

public class MyViewModel : INotifyPropertyChanged
{
    /******************************************************/
    /* Property that you have created two-way binding for */
    /******************************************************/
    private double _myProperty
    public double MyProperty
    {
        get { return _myProperty; }
        set
        {
            _myProperty = value;

            OnNotifyPropertyChanged("MyProperty");
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnNotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion INotifyPropertyChanged Members
}
KyleMit
  • 30,350
  • 66
  • 462
  • 664
sfogle
  • 386
  • 3
  • 7