Home > OS >  Command does not execute on form initialize for radio button
Command does not execute on form initialize for radio button

Time:11-18

My form has 2 radio buttons. When you press either one of them it executes a command that sets a string variable with the relative value for radio button set to true - this also has a CommandParameter that sends the value of the string Content into the Exectue function.

This works fine when a human is pressing a radio button. Variables get set and all is good.

However, I have coded in the xaml for one of the radio buttons to be set to checked by default - and this does not cause the command to be executed on startup of the form for the very first time. Hence the string variable that I hold the appropriate value for the radio button that is checked, never gets set.

How do I get my string variable recieve the value on startup from the Execute(param) method?

Here is the xaml:

    <StackPanel Grid.Row="4" Grid.Column="1" Margin="3"  Orientation="Horizontal">
            <RadioButton GroupName="LcType" Name="TsMapPane" HorizontalAlignment="Left" Checked="TsMapPane_Checked" IsChecked="True"
                         Command="{Binding Path=LcTypeCommand}" CommandParameter="{Binding ElementName=TsMapPaneTextBox, Path=Text}" >
                <RadioButton.Content>
                    <TextBlock Name="TsMapPaneTextBox" Text="TS_MAP_PANE"/>
                </RadioButton.Content>
            </RadioButton>
            <RadioButton GroupName="LcType" Margin="10 0 0 0"  Name="TsGroup" HorizontalAlignment="Left" Checked="TsGroup_Checked"
                         Command="{Binding Path=LcTypeCommand}" CommandParameter="{Binding ElementName=TsGroupTextBox, Path=Text}">
                <RadioButton.Content>
                    <TextBlock Name="TsGroupTextBox" Text="TS_GROUP"/>
                </RadioButton.Content>
            </RadioButton>
        </StackPanel>

Here is the ViewModel:

public ICommand LcTypeCommand { get; set; }

public MyViewModel()
{
      LcTypeCommand = new RelayCommand((param) => LcTypeExecute(param), () => true);
}

private void LcTypeExecute(object param)
{
    LcTypeName = param.ToString();
}

public string LcTypeName
{
    get => _lcTypeName;
    set => SetField(ref _lcTypeName, value);
}



CodePudding user response:

The command is called only when the user clicks on the button.
Changing the state of the RadioButton raises the Checked and Unchecked events. You can connect a command to the Checked event, but there is no guarantee that the IsChecked property will be changed after the listener is connected. Since both are specified in XAML.
In my opinion, the most correct would be to call the command in Code Behind after XAML initialization.

    InitializeComponent();

    if (TsMapPane.Command is ICommand command &&
        command.CanExecute(TsMapPane.CommandParameter))
    {
        command.Execute(TsMapPane.CommandParameter);
    }

P.S. You can add the following extension method to the Solution:

    public static partial class WinHelper
    {
        public static void TryExecute(this ICommandSource commandSource)
        {
            if (commandSource.Command is not ICommand command)
                return;

            if (command is RoutedCommand routedCommand)
            {
                IInputElement? target = commandSource.CommandTarget ?? commandSource as IInputElement;
                if (routedCommand.CanExecute(commandSource.CommandParameter, target))
                {
                    routedCommand.Execute(commandSource.CommandParameter, target);
                }
            }
            else
            {
                if (command.CanExecute(commandSource.CommandParameter))
                {
                    command.Execute(commandSource.CommandParameter);
                }
            }
        }
    }

Then the code will be simplified to this:

    InitializeComponent();

    TsMapPane.TryExecute();

shows a null value for "TsMapPane.CommandParameter"

At the time of XAML initialization, if the DataContext is assigned by an external container, bindings to the DataContext will not yet work. Therefore, you need to execute the command once in the Loaded event:

    public SomeWindow()
    {
        InitializeComponent();

        Loaded  = onl oaded;
    }

    private void onl oaded(object sender, RoutedEventArgs e)
    {
        Loaded -= onl oaded;
        TsMapPane.TryExecute();
    }
  • Related