Hi stackoverflow community, I'm new to the MVVM topic but was able to get some of the basics down. I worked on a few tutorials and implemented my own RealyCommand and a ViewModelBase.
I got my Buttons working with Command Binding and Enable/Disable with CanExecute was working as well.
MVVM Toolkit: After implementing MVVM Toolkit for messaging, I have looked into more examples on MS page and saw that the toolkit provides RelayCommand and a lot more features with way less code, so I wanted to replace my own MVVM code with code for MVVM Toolkit.
For the life of it, I can't figure out why the canExecute doesn't work, It updates the bool variables from true to false and vice versa but the button does not go enabled/disabled. What am I missing?
TestViewModel:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace WorkOrderApplication.ViewModels
{
public partial class TestViewModel : ObservableObject
{
public TestViewModel()
{
Testbutton1 = true;
Testbutton2 = true;
}
[ObservableProperty]
private bool _testbutton1;
[ObservableProperty]
private bool _testbutton2;
[RelayCommand(CanExecute = nameof(CanExecuteButton1))]
private void ClickButton1()
{
Testbutton1 = false;
Testbutton2 = true;
}
private bool CanExecuteButton1()
{
return Testbutton1;
}
[RelayCommand(CanExecute = nameof(CanExecuteButton2))]
public void ClickButton2()
{
Testbutton1 = true;
Testbutton2 = false;
}
private bool CanExecuteButton2()
{
return Testbutton2;
}
}
}
TestView:
<UserControl x:Class="WorkOrderApplication.Views.TestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:designer="clr-namespace:WorkOrderApplication.ViewModels.Designer"
xmlns:customcontrol="clr-namespace:WorkOrderApplication.Views.Controls"
xmlns:viewmodels="clr-namespace:WorkOrderApplication.ViewModels"
mc:Ignorable="d"
d:DesignWidth="1920"
d:DesignHeight="1080">
<UserControl.Resources>
<Style TargetType="Button" x:Key="RoundButton">
<Style.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="10" />
</Style>
</Style.Resources>
<Setter Property="FontSize" Value="30"/>
<Setter Property="Foreground" Value="white"/>
<Setter Property="Background" Value="green"/>
<Setter Property="Width" Value="130"/>
<Setter Property="Height" Value="50"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="940"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="0,0,0,0" Background="White">
<DockPanel Margin="0,0,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="135"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="166"/>
<ColumnDefinition Width="166"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Content="Button 1" Grid.Column="0"
Style="{DynamicResource RoundButton}"
Command="{Binding ClickButton1Command}">
</Button>
<Button Content="Button 2" Grid.Column="1"
Style="{DynamicResource RoundButton}"
Command="{Binding ClickButton2Command}">
</Button>
</Grid>
</DockPanel>
</Grid>
<Grid Grid.Row="1" Margin="0,0,0,0" Background="White">
<Label Content="Content:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" FontSize="60" Height="100" Width="300"/>
</Grid>
</Grid>
According to the docs you have to set the NotifyCanExecuteChangedFor
attribute
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace WorkOrderApplication.ViewModels
{
public partial class TestViewModel : ObservableObject
{
public TestViewModel()
{
Testbutton1 = true;
Testbutton2 = true;
}
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(ClickButton1Command))]
private bool _testbutton1;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(ClickButton2Command))]
private bool _testbutton2;
[RelayCommand(CanExecute = nameof(CanExecuteButton1))]
private void ClickButton1()
{
Testbutton1 = false;
Testbutton2 = true;
}
private bool CanExecuteButton1()
{
return Testbutton1;
}
[RelayCommand(CanExecute = nameof(CanExecuteButton2))]
public void ClickButton2()
{
Testbutton1 = true;
Testbutton2 = false;
}
private bool CanExecuteButton2()
{
return Testbutton2;
}
}
}