loki
loki

Reputation: 2966

How to access usercontrol (toolbar) from ViewModel in MVVM?

how to talk toolbar (it is a user control) on the button to enable a wait cursor. i have a ViewModel is inherited from viewmodelBase. But i can not use IsWorking on toolbar.

Below code is toolbar's code. i clicked select button. data is selecting from database. Cursor must be turn to wait.after Selecting, Cursor must return normal.



    <Button x:Name="Select"
            Content="select"
            Command="{Binding SelectCommand }">
        <Button.Style>
             <Style TargetType="{x:Type Button}">
                 <Setter Property="Cursor" Value="Arrow"/>
                 <Style.Triggers>
                     <DataTrigger Binding="{Binding Path=IsWorking}" Value="True">
                         <Setter Property="Cursor" Value="Wait"/>
                     </DataTrigger>
                 </Style.Triggers>
             </Style>
        </Button.Style>
    </Button>

ViewModelBase.cs: there is no inheritance with toolbar. it is a basemodel.

private bool _isWorking = false;
public bool IsWorking
{
    get { return _isWorking; }
    set
    {
        _isWorking = value;
        OnPropertyChanged("IsWorking");
    }
}

Here is the code from the view-model:

public class MainViewModel : ViewModelBase
{
    public void Select()
    {
        IsWorking = true;     cursor turn to wait mode
        // db Process...

        IsWorking = false;  cursor turn to hand mode
    }
}

How to communicate with toolbar from ViewModel? Click select Cursor must be turn Wait mode. after selection, cursor must be hand(default).

Changing the cursor in WPF sometimes works, sometimes doesn't

enter image description here

Upvotes: 1

Views: 3148

Answers (1)

Blachshma
Blachshma

Reputation: 17395

From what I see, your problem is that you're trying to bind from your UserControl back to the view/window in which it's located.

The usercontrol, of course, will not be able to bind like this. You have a few options:

1 . Give the UserControl the View's datacontext:

<local:UserControl1 DataContext="{Binding ElementName=MyWindow}" />

and then in your UserControl you can bind to the ViewModel's IsWorking directly:

<DataTrigger Binding="{Binding IsWorking}" Value="True">
  <Setter Property="Cursor" Value="Wait"/>
</DataTrigger>

2 . Create a Dependency Property on your UserControl and bind to it from the view:
In your usercontrol create a new DP:

public bool MyIsWorking
{
  get { return (bool)GetValue(MyIsWorkingProperty ); }
  set { SetValue(MyIsWorkingProperty , value); }
}

public static readonly DependencyProperty MyIsWorkingProperty =
        DependencyProperty.Register("MyIsWorking", typeof(bool), typeof(UserControl1),    new UIPropertyMetadata(false));

In the usercontrol's XAML bind to the DP:

<DataTrigger Binding="{Binding MyIsWorking}" Value="True">
        <Setter Property="Cursor" Value="Wait"/>
</DataTrigger>

In your window - bind the DP to the VM's IsWorking property:

<local:UserControl1 MyIsWorking="{Binding IsWorking, ElementName=MyWindow}" />

3 . Finally this will work but it's not recommended!!!**

<DataTrigger Binding="{Binding IsWorking, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="True">
    <Setter Property="Cursor" Value="Wait"/>
</DataTrigger>

What this does is tries to find the Window in the Visual Tree and use its DataContext. Why isn't it recommended? Because you might not be using this in a Window or you might not want it to be bound to the specific DataContext the containing Window is using. Either way, it IS another possibility.

Upvotes: 4

Related Questions