Reputation: 139
I am using C# and WPF to write a program which has a side menu like the one in the screenshot below.
The XAML Code for Menu Toggle Button 4 and 5 looks like this:
<ToggleButton x:Name="MenuBtn_4" Content="MENU TOGGLE BUTTON 4" />
<StackPanel x:Name="Submenu_4" Visibility="{Binding ElementName=MenuBtn_4,
Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter},
FallbackValue=Visible}">
<Button Content="SUBMENU BUTTON 1" />
<Button Content="SUBMENU BUTTON 2" />
</StackPanel>
<ToggleButton x:Name="MenuBtn_5" Content="MENU TOGGLE BUTTON 5" />
<StackPanel x:Name="Submenu_5" Visibility="{Binding ElementName=MenuBtn_5,
Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter},
FallbackValue=Visible}">
<Button Content="SUBMENU BUTTON 1" />
<Button Content="SUBMENU BUTTON 2" />
</StackPanel>
Right now if I click on the MenuToggleButton
, the StackPanel
with Submenu Buttons below becomes visible. If I click the ToggleButton
again it collapses, which is what I want.
But if the StackPanel
of one Menu ToggleButton
is visible and I click on another ToggleButton
the first one stays visible. I would like it so that when another Menu ToggleButton
is checked, the previously visible stack panels of the other Menu toggle buttons collapse. I tried solving this with MultiBinding
but I cannot seem to make it work. Does anyone have any ideas how I could do this?
Upvotes: 0
Views: 1317
Reputation: 7325
As "quick and dirty" you can solve it with XAML only if you put a hidden RadioButton
and RadioButton
s have a property GroupName
, which provides that only one RadioButton
is checked:
<StackPanel>
<RadioButton x:Name="rb11" GroupName="G1" Visibility="Collapsed"/>
<ToggleButton x:Name="tb11" IsChecked="{Binding IsChecked, ElementName=rb11}" Content="111" />
<StackPanel Visibility="{Binding IsChecked, ElementName=rb11, Converter={StaticResource Convert}}">
<TextBlock Text="1111111111"/>
<TextBlock Text="1111111111"/>
</StackPanel>
<RadioButton x:Name="rb22" GroupName="G1" Visibility="Collapsed"/>
<ToggleButton x:Name="tb22" IsChecked="{Binding IsChecked, ElementName=rb22}" Content="222" />
<StackPanel Visibility="{Binding IsChecked, ElementName=rb22, Converter={StaticResource Convert}}">
<TextBlock Text="22222222222"/>
<TextBlock Text="22222222222"/>
</StackPanel>
</StackPanel>
Upvotes: 0
Reputation: 4943
You can use a MultiDataTrigger
in a Style
instead of a MultiBinding
, causing each StackPanel
to be visible only when the ToggleButton
is checked and the other ToggleButton
is not.
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
<StackPanel>
<ToggleButton x:Name="MenuBtn_4" Content="MENU TOGGLE BUTTON 4" Margin="0 5 0 5"/>
<StackPanel x:Name="Submenu_4">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=MenuBtn_4, Path=IsChecked}" Value="True"/>
<Condition Binding="{Binding ElementName=MenuBtn_5, Path=IsChecked}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Control.Visibility" Value="Visible"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<StackPanel.Triggers>
</StackPanel.Triggers>
<Button Content="SUBMENU BUTTON 1" />
<Button Content="SUBMENU BUTTON 2" />
</StackPanel>
<ToggleButton x:Name="MenuBtn_5" Content="MENU TOGGLE BUTTON 5" Margin="0 5 0 5"/>
<StackPanel x:Name="Submenu_5">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=MenuBtn_5, Path=IsChecked}" Value="True"/>
<Condition Binding="{Binding ElementName=MenuBtn_4, Path=IsChecked}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Control.Visibility" Value="Visible"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Button Content="SUBMENU BUTTON 1" />
<Button Content="SUBMENU BUTTON 2" />
</StackPanel>
</StackPanel>
However, this won't force any ToggleButton
to get unchecked when you check the other, and that's because it's not a correct use of the ToggleButton
class. If you want truly exclusive behavior, you can use RadioButton
as suggested in another answer or you could change the user experience by displaying sub menus when the mouse is over one of the header buttons instead of when a header is clicked.
Upvotes: 1
Reputation: 1107
You are facing such issue just because your window allows to check multiple ToggleButtons
. Your issue can be resolved by implementing a logic which allows only one ToggleButton
to be selected at a time.
And for this, you can use RadioButton
which looks like ToggleButton in UI.
<RadioButton x:Name="MenuBtn_4" Content="MENU TOGGLE BUTTON 4" GroupName="grp1"
Style="{StaticResource {x:Type ToggleButton}}" cal:Message.Attach="MenuSelect"/>
<StackPanel x:Name="Submenu_4" Visibility="{Binding ElementName=MenuBtn_4,
Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter},
FallbackValue=Visible}">
<Button Style="{StaticResource MenuBtn}" Content="SUBMENU BUTTON 1"
cal:Message.Attach="SubmenuSelect"/>
<Button Style="{StaticResource MenuBtn}" Content="SUBMENU BUTTON 2"
cal:Message.Attach="SubmenuSelect"/>
</StackPanel>
<RadioButton x:Name="MenuBtn_5" Content="MENU TOGGLE BUTTON 5" GroupName="grp1"
Style="{StaticResource {x:Type ToggleButton}}" cal:Message.Attach="MenuSelect"/>
<StackPanel x:Name="Submenu_5" Visibility="{Binding ElementName=MenuBtn_5,
Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter},
FallbackValue=Visible}">
<Button Style="{StaticResource MenuBtn}" Content="SUBMENU BUTTON 1"
cal:Message.Attach="SubmenuSelect"/>
<Button Style="{StaticResource MenuBtn}" Content="SUBMENU BUTTON 2"
cal:Message.Attach="SubmenuSelect"/>
</StackPanel>
NOTE: if you can see, I have used style {StaticResource {x:Type ToggleButton}}
but I think it should also work with your custom style {StaticResource ToggleMenuBtn}
. But that you need to check.
Upvotes: 2