Caliburn.micro binds the visibility element to the viewmodel function, not a property

first of all - I'm sorry if this is a duplicate - looked around for a while and couldn't find an answer to this,

We are using caliburn.micro, so the solution must use this tool.

We have a view consisting of 9 buttons, however - not all of them will be visible at the same time, it depends on the events in the system. Each visibility of each button is visible or collapsed depending on the current state, but since this is a large number of buttons, and may increase in the future, I would rather have one function for this (get a name or enumeration and return the visibility) instead of having a large number properties to bind each button to.

Is this even an option? I couldn't find a way to do this in the usual way.

Since events are received externally, the software we develop at this level is not really an option (or at least not correct)

Edit: here's the snippet of the view I want to change:

            <Grid Margin="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="120" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>

                <uiviews:PhonePadView Grid.Column="0" x:Name="DestinationDn" cal:Bind.Model="UI.ViewModels.PhonePadViewModel" />

                <Button  Grid.Column="1" Content="Dial" Style="{StaticResource PhonePadBasicFunctionsButtons}" x:Name="MakeCall" Visibility="{Binding btnMakeCallVisibility}" />
                <Button  Grid.Column="1" Content="Answer" Style="{StaticResource PhonePadBasicFunctionsButtons}" x:Name="AnswerCall" Visibility="{Binding btnAnswerCallVisibility}" />
                <Button  Grid.Column="1" Content="Hang-up" Style="{StaticResource PhonePadBasicFunctionsButtons}" x:Name="ReleaseCall" Visibility="{Binding btnReleaseCallVisibility}" />
                <Button  Grid.Column="1" Content="Hold" Style="{StaticResource PhonePadBasicFunctionsButtons}" x:Name="HoldCall" Visibility="{Binding btnHoldCallVisibility}" />

            </Grid>

      

As you can see, I need to have a different property for each of the buttons, and I refuse to believe that this is the only way, I have a property containing the current status (phone is ringing, in a call, dialing, etc.), and it's easy to have a function in a virtual machine to indicate which button should be visible and which shouldn't, and furthermore, we currently have 9 buttons, but it can expand just as easily, so I'm looking for the most modular code here

+3


source to share


2 answers


Out of the box, if you name anything with the IsVisible suffix, Caliburn Micro will toggle the visibility.

In view:

<Grid Name="ConfigEditorIsVisible">
    <TextBlock>Test</TextBlock>
</Grid>

      



In the ViewModel:

public bool ConfigEditorIsVisible { get; set; }

      

+5


source


So ... in the end this is what I did: in a virtual machine:

    private HashSet<string> actionsEnabledSet = null;
    public HashSet<string> ActionsEnabledSet
    {
        get { return actionsEnabledSet; }
        set
        {
            actionsEnabledSet = value;
            NotifyOfPropertyChange(() => ActionsEnabledSet);
        }
    }

      

Along with changing the hashset based on the elements I want to see.

A (multi) converter with conversion function:

    public object Convert(object[] value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
    {
        if (value[0].GetType() == typeof(HashSet<string>))
        {
            if (value[1].GetType() == typeof(string))
            {
                if (((HashSet<string>)value[0]).Contains((string)value[1]))
                    return Visibility.Visible;
            }
        }
        return Visibility.Collapsed;
    }

      

View Button Style: (To avoid code duplication as much as I could)



    <Style TargetType="Button" x:Key="PhonePadBasicFunctionsButtons" >
        <Setter Property="Margin" Value="0,0,0,0" />
        <Setter Property="Focusable" Value="False" />
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="Width" Value="75" />
        <Setter Property="Visibility">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource PhoneActionVisibilityConverter1}">
                    <Binding Path="ActionsEnabledSet" Mode="OneWay"/>
                    <Binding RelativeSource="{RelativeSource Self}" Path="Tag" />
                </MultiBinding>
            </Setter.Value>
        </Setter>
    </Style>

      

And a button stack panel that looks like this:

                <Button  Content="Call" Style="{StaticResource PhonePadBasicFunctionsButtons}" x:Name="MakeCall" Tag="MakeCall" cal:Message.Attach="MakeCall" />
                <Button  Content="Answer" Style="{StaticResource PhonePadBasicFunctionsButtons}" x:Name="AnswerCall" Tag="AnswerCall" cal:Message.Attach="AnswerCall" />

      

Actually I couldn't find a way to bind "tag" to "x: name", but adding new buttons is as easy as adding one line and it would be better to have the code this way, would like to have any ideas on how to do it better, i think it is elegant, but i have a feeling it is easier to read / implement.

I had to use multibinding as using covnerterproperty is not an option - you cannot bind an element to a property as it seems, hope this helps someone in the future - was a good call :)

And thank you to everyone who tried to help - you took me out of the box and were actually looking for an answer!

0


source







All Articles