Reputation: 218
first of all - I'm sorry if it's a duplicate - been looking around for awhile and couldn't find an answer to that,
We're using caliburn.micro so the solution must be using this tool.
We have a view that is consisted of 9 buttons, however - not all of them will be visible in the same time, it depends on events on the system. Each button visibility to either visible or collapsed based on current status but since it is a large number of buttons, and may increase in the future I'd rather have a single function to do this (receiving a name or an enum and returning visibility) rather than having a large amount of properties to bind each button to.
Is it even an option? I couldn't seem to find a way of doing it in any conventional way.
Since the events are being received from outside the software we're developing doing this on the view level is not really an option (or at least - not a right one)
Edit: Here's a snippet of the view that I wish to modify:
<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 this is the only way, I do have a property holding the current status (phone is ringing, in a call, dialing etc.) and it's easy to have a function on the VM to tell which button should be visible and which shouldn't, and on top of it we currently have 9 buttons but it may just as easily expand more, so I'm looking for the most modular code possible here
Upvotes: 5
Views: 5051
Reputation: 3388
Out of the box, if you name something with the "IsVisible" suffix, Caliburn Micro will toggle visibility.
On the View:
<Grid Name="ConfigEditorIsVisible">
<TextBlock>Test</TextBlock>
</Grid>
On the ViewModel:
public bool ConfigEditorIsVisible { get; set; }
Upvotes: 17
Reputation: 218
So... in the end this is what I did: on the VM:
private HashSet<string> actionsEnabledSet = null;
public HashSet<string> ActionsEnabledSet
{
get { return actionsEnabledSet; }
set
{
actionsEnabledSet = value;
NotifyOfPropertyChange(() => ActionsEnabledSet);
}
}
Alongside changing the hashset based on the items I wish to have visible.
A (multi) converter with the convert 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 styling: (To avoid duplicate code 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 stackpanel of the buttons that looks like that:
<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" />
Really annoyed I couldn't find a way to bind "tag" to "x:name", but adding new buttons is as easy as adding a single line and it feels better to have the code this way, would love to have any ideas on how to make this better, I think it's elegant but I have a feeling it could be 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'll help to someone in the future - was a nice challange :)
And thank you for everyone who tried to help - you got me out of my box and actually looking for an answer!
Upvotes: 0