C
C#7mo ago
stigzler

✅ How to use IRelayCommand in CommunityToolkit.Mvvm with parameters?

I'm just learning WPF and also the community toolkit. I can get RelayCommands working OK if they're parameter-less, but struggling to implement a command bound to a Toggle Button to toggle a bool property on a databound control. My working approach to simple commands:
public IRelayCommand LogOutCMD { get; set; }
private void SetupCommands() // this is called at startup
{
LogOutCMD = new RelayCommand(LogOut);
}
private void LogOut()
{
// does stuff
}
public IRelayCommand LogOutCMD { get; set; }
private void SetupCommands() // this is called at startup
{
LogOutCMD = new RelayCommand(LogOut);
}
private void LogOut()
{
// does stuff
}
However, I have tried something similar for the ToggleButton:
public bool CodeNumberingVisible { get => codeNumberingVisible; set => SetProperty(ref codeNumberingVisible, value); }
public IRelayCommand SetCodeNumberingVisibleCMD { get; set; }
SetCodeNumberingVisibleCMD = new RelayCommand<bool>(SetCodeNumberingVisible);
private void SetCodeNumberingVisible(bool visible)
{
CodeNumberingVisible = visible;
}
public bool CodeNumberingVisible { get => codeNumberingVisible; set => SetProperty(ref codeNumberingVisible, value); }
public IRelayCommand SetCodeNumberingVisibleCMD { get; set; }
SetCodeNumberingVisibleCMD = new RelayCommand<bool>(SetCodeNumberingVisible);
private void SetCodeNumberingVisible(bool visible)
{
CodeNumberingVisible = visible;
}
The button and control xaml:
<ToggleButton x:Name="CodeNumberVisibleBT" ToolTip="Toggle Code Numbers"
Command="{Binding SetCodeNumberingVisibleCMD}"
IsChecked="{Binding CodeNumberingVisible}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}"/>
<syncfusion:EditControl ShowLineNumber="{Binding CodeNumberingVisible}"/>
<ToggleButton x:Name="CodeNumberVisibleBT" ToolTip="Toggle Code Numbers"
Command="{Binding SetCodeNumberingVisibleCMD}"
IsChecked="{Binding CodeNumberingVisible}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}"/>
<syncfusion:EditControl ShowLineNumber="{Binding CodeNumberingVisible}"/>
However, this renders the button inoperable (no rollover highlighting, command doesn't execute) - it works without the Command Binding. Any ideas? EDIT: I've just realised that I don't technically need a Command here, I can just bind the ToggleButton's IsChecked property to the property directly. However, I'm still intersted to know why the above broke the ToggleButton and how to send parameters via cmmands using the Community Toolkit.
35 Replies
Buddy
Buddy7mo ago
Community toolkit uses source generators
[RelayCommand]
private void Foo(bool bar)
{


}
[RelayCommand]
private void Foo(bool bar)
{


}
Note that the class must be declared as partial The source generator will then generate a property called FooCommand which you can use in your XAML code https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/relaycommand#command-parameters
stigzler
stigzlerOP7mo ago
Thanks for the reply. Have just tried it in my code, but still the ToggleButton is not working:
[RelayCommand]
private void TestRC(bool boolean)
{
Debug.WriteLine($"TestRC woz ere: {boolean}");
}
[RelayCommand]
private void TestRC(bool boolean)
{
Debug.WriteLine($"TestRC woz ere: {boolean}");
}
<ToggleButton x:Name="CodeOutliningVisibleBT" ToolTip="Toggle Code Outlining"
Command="{Binding TestRCCommand}">
<imaging:CrispImage Width="16" Height="16" Moniker="{x:Static catalog:KnownMonikers.OrderedList}" />
</ToggleButton>
<ToggleButton x:Name="CodeOutliningVisibleBT" ToolTip="Toggle Code Outlining"
Command="{Binding TestRCCommand}">
<imaging:CrispImage Width="16" Height="16" Moniker="{x:Static catalog:KnownMonikers.OrderedList}" />
</ToggleButton>
BUtton starts working if I remove the Command Also tried this, but no dice:
public bool TrueValue { get; set; }
[RelayCommand(CanExecute = nameof(TrueValue))]
private void TestRC(bool boolean)
{
Debug.WriteLine($"TestRC woz ere: {boolean}");
}
public bool TrueValue { get; set; }
[RelayCommand(CanExecute = nameof(TrueValue))]
private void TestRC(bool boolean)
{
Debug.WriteLine($"TestRC woz ere: {boolean}");
}
leowest
leowest7mo ago
u're not defining a parameter so it breaks the toolkit apparently so u either make it
[ObservableProperty]
private bool _trueValue;

[RelayCommand(CanExecute = nameof(TrueValue))]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}
[ObservableProperty]
private bool _trueValue;

[RelayCommand(CanExecute = nameof(TrueValue))]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}
Or you pass in a parameter I think the only exception is if ur passing a CT
stigzler
stigzlerOP7mo ago
thanks for the reply, however:
public bool TrueValue { get; set; } = true;

[RelayCommand]
private void TestRC(bool boolean)
{
Debug.WriteLine($"TestRC woz ere: {boolean}");
}
public bool TrueValue { get; set; } = true;

[RelayCommand]
private void TestRC(bool boolean)
{
Debug.WriteLine($"TestRC woz ere: {boolean}");
}
doesn't work either.
leowest
leowest7mo ago
it has parameter I just explained above
stigzler
stigzlerOP7mo ago
So I'm trying:
[ObservableProperty]
private bool _trueValue;

[RelayCommand(CanExecute = nameof(TrueValue))]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}
[ObservableProperty]
private bool _trueValue;

[RelayCommand(CanExecute = nameof(TrueValue))]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}
but weirdly it won't compile. It's also not registering the error in the error window Do I have to define the TreuValue property as well?
leowest
leowest7mo ago
no CTK should do it for u I assume u are using it by the RelayCommand attribute and xaml code
stigzler
stigzlerOP7mo ago
just removed the code and it compiles fine.
leowest
leowest7mo ago
what part u removed
stigzler
stigzlerOP7mo ago
my xaml is aper that in the OP -
[ObservableProperty]
private bool _trueValue;

[RelayCommand(CanExecute = nameof(TrueValue))]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}
[ObservableProperty]
private bool _trueValue;

[RelayCommand(CanExecute = nameof(TrueValue))]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}
leowest
leowest7mo ago
yes I was referring to Binding TestRCCommand since u have RelayCommand and the xaml like that I assumed u are using CTK well that should compile
stigzler
stigzlerOP7mo ago
leowest
leowest7mo ago
try this
stigzler
stigzlerOP7mo ago
ah wait The name 'TrueValue' does not exist in the current context
leowest
leowest7mo ago
well CTK generates it for u hover your mouse over ObservableProperty and it will show u how it works Try this instead
public bool TrueValue { get; set; } = true;

[RelayCommand(CanExecute = nameof(CanTest))]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}

private bool CanTest()
{
return TrueValue;
}
public bool TrueValue { get; set; } = true;

[RelayCommand(CanExecute = nameof(CanTest))]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}

private bool CanTest()
{
return TrueValue;
}
stigzler
stigzlerOP7mo ago
That did it - wow - so I have to pass all that in - I wonder why it doens't work with just [RelayCommand] without the can execute?
leowest
leowest7mo ago
I mean it works
stigzler
stigzlerOP7mo ago
hah - well yeah
leowest
leowest7mo ago
u can do just
[RelayCommand]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}
[RelayCommand]
private void TestRC()
{
Debug.WriteLine($"TestRC woz ere: {TrueValue}");
}
but if u want to disable the button yada yada u need something to test against and the way u had it with the parameter but without having a parameter in the xaml it breaks it
stigzler
stigzlerOP7mo ago
That's the original problem - just that was rendering the button unusable
leowest
leowest7mo ago
shouldn't thou its not checking against anything
stigzler
stigzlerOP7mo ago
ikr
leowest
leowest7mo ago
I mean its a toogle button so it would go into disabled but u should still be able to toggle it
stigzler
stigzlerOP7mo ago
ah yeah - let me try and re-author naw - i give up - tried the below but button still not working:
<ToggleButton x:Name="CodeOutliningVisibleBT" ToolTip="Toggle Code Outlining" Command="{Binding TestRCCommand}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}">
<imaging:CrispImage Width="16" Height="16" Moniker="{x:Static catalog:KnownMonikers.OrderedList}" />
</ToggleButton>
<ToggleButton x:Name="CodeOutliningVisibleBT" ToolTip="Toggle Code Outlining" Command="{Binding TestRCCommand}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}">
<imaging:CrispImage Width="16" Height="16" Moniker="{x:Static catalog:KnownMonikers.OrderedList}" />
</ToggleButton>
[RelayCommand]
private void TestRC(bool state)
{
Debug.WriteLine($"TestRC woz ere: {state}");
}
[RelayCommand]
private void TestRC(bool state)
{
Debug.WriteLine($"TestRC woz ere: {state}");
}
WPF's great, but it is like talking with the world's largest pedant.... thanks for your help though - found a work around
leowest
leowest7mo ago
stigzler
stigzlerOP7mo ago
😕
leowest
leowest7mo ago
not sure what to tell u, its the exact same xaml u posted above and the exact same method
stigzler
stigzlerOP7mo ago
then god knows baffles me, wpf
leowest
leowest7mo ago
try removing the element inside and see if it works because on mine I just used an image since I dont have that lib maybe that lib hide hittest or something which would make sense
stigzler
stigzlerOP7mo ago
<ToggleButton x:Name="CodeOutliningVisibleBT" Content="Dave" ToolTip="Toggle Code Outlining" Command="{Binding TestRCCommand}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}">
</ToggleButton>
<ToggleButton x:Name="CodeOutliningVisibleBT" Content="Dave" ToolTip="Toggle Code Outlining" Command="{Binding TestRCCommand}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}">
</ToggleButton>
Still no dice - but have found that button is disabled. If I remove the Command attribute in live editor, then the button is enabled again - thus it is something to do with the CanExecute part of the RrelayCommand. No idea why it's defaulting to false nemmind - I'll use the workaround for now thanks again 👍
Auger
Auger7mo ago
Have you tried something like
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(TestRCCommand))]
private bool _isCodeOutliningVisible;

[RelayCommand(CanExecute = nameof(IsCodeOutliningVisible))]
private void TestRC(bool isCodeOutliningVisible)
{
// Note: You likely don't need a param, you have the value available as a class field

// Implementation...
}
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(TestRCCommand))]
private bool _isCodeOutliningVisible;

[RelayCommand(CanExecute = nameof(IsCodeOutliningVisible))]
private void TestRC(bool isCodeOutliningVisible)
{
// Note: You likely don't need a param, you have the value available as a class field

// Implementation...
}
<ToggleButton x:Name = "CodeOutliningVisibleBT"
Content="Dave"
ToolTip="Toggle Code Outlining"
IsChecked="{Binding IsCodeOutliningVisible, Mode=TwoWay}"
Command="{Binding TestRCCommand}"
CommandParameter="{Binding IsCodeOutliningVisible}">
</ToggleButton>
<ToggleButton x:Name = "CodeOutliningVisibleBT"
Content="Dave"
ToolTip="Toggle Code Outlining"
IsChecked="{Binding IsCodeOutliningVisible, Mode=TwoWay}"
Command="{Binding TestRCCommand}"
CommandParameter="{Binding IsCodeOutliningVisible}">
</ToggleButton>
Although, the CanExecute becoming false will no longer allow you to execute that command to turn it back to true, so instead you could try
[ObservableProperty]
private bool _isCodeOutliningVisible;

[RelayCommand]
private void TestRC()
{
// Implementation using IsCodeOutliningVisible

if (IsCodeOutliningVisible)
{
// ...
}
}
[ObservableProperty]
private bool _isCodeOutliningVisible;

[RelayCommand]
private void TestRC()
{
// Implementation using IsCodeOutliningVisible

if (IsCodeOutliningVisible)
{
// ...
}
}
<ToggleButton x:Name = "CodeOutliningVisibleBT"
Content="Dave"
ToolTip="Toggle Code Outlining"
IsChecked="{Binding IsCodeOutliningVisible, Mode=TwoWay}"
Command="{Binding TestRCCommand}">
</ToggleButton>
<ToggleButton x:Name = "CodeOutliningVisibleBT"
Content="Dave"
ToolTip="Toggle Code Outlining"
IsChecked="{Binding IsCodeOutliningVisible, Mode=TwoWay}"
Command="{Binding TestRCCommand}">
</ToggleButton>
stigzler
stigzlerOP7mo ago
Thanks @Auger - yeah we were there a number of posts ago - no dice
Auger
Auger7mo ago
Specifically the Mode=TwoWay part may help if you plan to set that value from code and from the UI toggle
stigzler
stigzlerOP7mo ago
ah! you may have apoint there
Auger
Auger7mo ago
There is also a dialog window in VS that is "XAML Binding Failures" I think. That's a good one to keep your eye on while running the app
Want results from more Discord servers?
Add your server