Home > database >  How to Toggle Visibility Between a Button and a Stack Panel Containing Two Buttons
How to Toggle Visibility Between a Button and a Stack Panel Containing Two Buttons

Time:09-30

I am having difficulty figuring out how to toggle the visibility between three buttons. Here is the scenario:

  • I have 3 buttons on a user control, an Edit button, an OK button, and a Cancel button.
  • The Ok and Cancel buttons are grouped together in a stack panel.
  • The Edit button is by itself.
  • I would like when the Edit button is pressed, that it (the Edit button) is hidden and the stack panel containing the Ok and Cancel buttons are shown.
  • When either the Cancel or Ok buttons are pressed, they are hidden, and the Edit button is shown again.
  • There will be 7 lines on this form that are all very similar, with a label, text box, and an edit button.
  • Is it possible to use only a few methods to control the visibility of all of the buttons/ stack panels.
  • i.e. Can I have one Edit method and show the stack panel depending on the text box control name/ binding, instead of having to right 7 methods for showing the stack panel, 7 Ok methods and 7 cancel methods?

Here is the line on the form with the Edit button:

Edit Button

And here is the line on the form with the Ok and Cancel buttons:

Ok and Cancel Buttons

Here is the XAML code that I've come up with for this line:

<StackPanel
        Orientation="Horizontal"
        HorizontalAlignment="Center"
        Grid.Row="2"
        Grid.Column="0"
        Grid.ColumnSpan="4">
    <Label
        Style="{StaticResource DeviceInfoPropertyLabelStyle}">
        CONTROLLER NAME:
    </Label>
    <TextBox
        Text="{Binding ControllerName}"
        Style="{StaticResource DeviceInfoTextBoxStyle}" />
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <StackPanel
            Orientation="Horizontal"
            Grid.Column="0">

            <Button
                Command="{Binding EditCommand}"
                Visibility="{Binding IsEditButtonVisible, Converter={StaticResource BoolToVisibilityConverter}, FallbackValue=Collapsed}"
                Style="{StaticResource DeviceInfoEditButtonStyle}">
                Edit
            </Button>
        </StackPanel>
        <StackPanel
            x:Name="EditControllerNameStackPanel"
            Orientation="Horizontal"
            Grid.Column="0"
            Visibility="{Binding IsOkCancelButtonVisible, Converter={StaticResource BoolToVisibilityConverter}, FallbackValue=Visible}">
            <Button
                Command="{Binding OkEditCommand}"
                Style="{StaticResource DeviceInfoEditOkButtonStyle}">
                OK
            </Button>
            <Button
                Command="{Binding  CancelEditCommand}"
                Style="{StaticResource DeviceInfoEditCancelButtonStyle}">
                CANCEL
            </Button>
        </StackPanel>
    </Grid>
</StackPanel>

Here is the code in the ViewModel that I have so far. It's only a skeleton at this point:

public bool IsEditButtonVisible
{
    get
    {
        bool output = false;
        if (true)
        {
            return true;
        }

        return output;
    }
}

public bool IsOkCancelButtonVisible
{
    get => true;
}


[RelayCommand]
private void Edit()
{
    if (true)
    {

    } 
}

[RelayCommand]
private void OkEdit()
{

}

[RelayCommand]
private void CancelEdit()
{

}

Note that I am using the MVVM Community Toolkit.

Let me know if I need to provide any additional information.

Thanks

CodePudding user response:

You can use just one boolean to toggle the visibility. Change BoolToVisibilityConverter code a bit..

public class BoolToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool b)
        {
            if (parameter is string str && str == "Inverse")
                return b ? Visibility.Hidden : Visibility.Visible;
            return b ? Visibility.Visible : Visibility.Hidden;
        }

        return Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Edit button

<Button
    Visibility="{Binding IsEditButtonVisible, Converter={StaticResource BoolToVisibilityConverter}}">

OK/Cancel stackpanel

<StackPanel
    Visibility="{Binding IsEditButtonVisible, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=Inverse}">

ViewModel (sorry I don't use MVVM Community Toolkit)

public class ViewModel : INotifyPropertyChanged
{
    
    private bool _isEditButtonVisible;

    public bool IsEditButtonVisible
    {
        set
        {
            _isEditButtonVisible = value;
            OnPropertyChanged(nameof(IsEditButtonVisible));
        }
        get => _isEditButtonVisible;
    }
    
    private void Edit()
    {
        IsEditButtonVisible = false;
    }

    private void Ok()
    {
        IsEditButtonVisible = true;
    }

    private void Cancel()
    {
        IsEditButtonVisible = true;
    }
    
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    
    
    // other code
}

To apply the same logic over the other 7 similar groups, you must have at least 7 booleans, but you can have 3 commands only, where you can pass the name of the group to the command, and the command will toggle the appropriate group based on the passed parameter

In View

<Button
    Command="{Binding OkCommand}"
    CommandParameter="group1">
    OK
</Button>

In ViewModel

private void Edit(string commandParameter)
{
    IsEdit1ButtonVisible = commandParameter != "group1";
    IsEdit2ButtonVisible = commandParameter != "group2";
    IsEdit3ButtonVisible = commandParameter != "group3";
    // etc...
}

private void Ok(string commandParameter)
{
    IsEdit1ButtonVisible = commandParameter == "group1";
    IsEdit2ButtonVisible = commandParameter == "group2";
    IsEdit3ButtonVisible = commandParameter == "group3";
    // etc...
}

private void Cancel(string commandParameter)
{
    IsEdit1ButtonVisible = commandParameter == "group1";
    IsEdit2ButtonVisible = commandParameter == "group2";
    IsEdit3ButtonVisible = commandParameter == "group3";
    // etc...
}
  • Related