My MVVM code requires hooking up a WPF Toggle button to a ViewModel.
The requirement is that when the Toggle button is 'Clicked' it executes the bound command changing the IsConnected property (bool). This property should define the visual state of thee toggle button.
What actually happens once I click the toggle button, it fires the bound command but irrespective of the IsConnected property value it changes its visual state to checked. What I want is the visual state of the toggle button to be dependent on the IsConnected property.
How can I avoid this race condition or prevent the Checked event from firing?
The XAML code is:
<ToggleButton Name="btnConnect"
DataContext="{Binding someViewModel, Source={StaticResource Locator}}"
IsChecked="{Binding Path=IsConnected, Mode=OneWay}"
Command="{Binding ConnectCommand}">
</ToggleButton>
Snapshot of the ViewModel:
public someViewModel()
{
Task.Factory.StartNew(() => Initialize());
}
public bool IsConnected
{
get
{
return m_bConnected;
}
set
{
Set<bool>(() => this.Connected, ref m_bConnected, value);
}
}
private void Initialize()
{
// Init Motion controller connection
ConnectCommand = new RelayCommand(ConnectMethod);
}
public RelayCommand ConnectCommand
{
get;
private set;
}
public void ConnectMethod()
{
try
{
// When in simulation mode
//m_API.OpenCommSimulator();
m_API.OpenCommEthernet("192.168.0.139", 731);
if (m_API.IsConnected)
Connected = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "CONNECTION ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
I ran into the same problem and found a simple solution:
Since we are binding a command to react when a user clicks on the Togglebutton
in this scenario, we have all we need. Just raise a PropertyChanged
Event for the property bound to IsChecked
. In your case you should raise the event for Isconnected
and this would be the first thing to do in your ConnectMethod
. This ensures that Togglebutton
stays in the state until the property realy changes.
Explanation:
This works because the change is only made on the visual state and the underlying property is not changed as expected for OneWay
Binding. Thus the property has still it's unchanged value and with raising the PropertyChanged
Event the Togglebutton
is forced to sync it's visual state with the value of the property and keep its state. When the property gets changed for real the PropertyChanged
Event is automatically raised again and the Togglebutton
can finally change its state as wished.
Hopefully this answer helps others running into this problem and searching for a solution