Binding visibility of rectangle control to button's isEnabled property - c#

I have several buttons, each implemented as a UserControl, on a screen, and only 1 will be enabled at a time. Now there is a sidebar type Rectangle next to all buttons in the UserControl, which should only be visible for 1 button, whichever is enabled. Tried several bindings to control the visibility of the rectangle with IsEnabled, but failed. Also have a visibility converter ready. Here's my code:
<Grid>
<Button Style="{StaticResource MenuButtonStyle}" x:Name="BtnUC">
<Button.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Fill="LightGray" Margin="-4,0,0,0">
</Rectangle>
<Viewbox ....
</Viewbox>
</Grid>
</Button.Content>
</Button>
</Grid>

Create an instance of a BooleanToVisibilityConverter converter in any resources in scope.
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
Then bind the Visibility of the rectangle to the IsEnabled property of your button by referring to it using the element name BtnUC. By specifying the converter, true will be converted to Visible and false to Collapsed.
<Rectangle Grid.Column="0" Fill="LightGray" Margin="-4,0,0,0"
Visibility="{Binding IsEnabled, ElementName=BtnUC, Converter={StaticResource BooleanToVisibilityConverter}}"/>
Alternatively, if there is no button name, refer to the parent Button via RelativeSource.
<Rectangle Grid.Column="0" Fill="LightGray" Margin="-4,0,0,0"
Visibility="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType={x:Type Button}}, Converter={StaticResource BooleanToVisibilityConverter}}"/>

You could use a Style with a DataTrigger that sets the Visibility property of the Rectangle based on the value of the IsEnabled property of the Button:
<Rectangle Grid.Column="0" Fill="LightGray" Margin="-4,0,0,0">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled,RelativeSource={RelativeSource AncestorType=Button}}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>

Related

How can I apply style based on a trigger property to a content control?

In the current WPF application that I am working on, I have to invert the color of an icon when the mouse is pressed on (when property isPressed=true ). The reason why I need to do is I want to keep the consistency of the application with regard to the icon color and background. But this icon is embedded within a button which when clicked displays a similar color and hence the icon is not visible
As my style trigger picks up the red color that I have set but the color of the geometry is not changed. Is there any way I can use this style trigger to set the color of the geometry also to Red when (isPressed=true)?
Here is my code
My Style is as follows
<Style x:Key="ButtonBackground" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="Content" Value="yellow" />
</Trigger>
</Style.Triggers>
</Style>
I tried setting a setter property to content as yellow just to see if it works but it did not work
The part where it is being used is as follows
<Border BorderBrush="{StaticResource ContentBackground}" BorderThickness="0,0,0,1">
<Button
x:Name="NameButton"
Style="{StaticResource ButtonBackground}"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<ContentControl x:Name="Icon"
Width="25"
Height="25"
">
</ContentControl>
<TextBlock Text="{Binding Name}"
"/>
</StackPanel>
</Grid>
</Button>
</Border>
As shown in the images as well the style is picked up by the textblock but I do not know how I can add this style to the contentcontrol which has the icons
Edit :- Example of icon specified in the application
<DataTemplate x:Key="FolderIcon">
<Path
Fill="#047F89"
Data="....."/>
</DataTemplate>
You have to bind the Fill property of the Path to the parent Control element's Control.Foreground (or Button.Foreground) instead of setting it directly. Now the icon color will adapt to the Foreground value assigned by the trigger. I also removed the redundant Grid of the Button.Content and the Content Setter of the Trigger as it would remove the icon Path element every time the Button is pressed and added the default Forground value to the Style (moved from Path.Fill to Style-Setter):
<Style x:Key="ButtonBackground" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="#047F89" />
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
<Button x:Name="NameButton"
Style="{StaticResource ButtonBackground}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Path Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Control}, Path=Foreground}"
Height="16"
Width="16"
Stretch="Uniform"
VerticalAlignment="Center"
Margin="5,0,0,0"
Data="....."/>
<TextBlock Text="{Binding Name}"
TextTrimming="WordEllipsis"
VerticalAlignment="Center"
Margin="5,0,0,0"/>
<StackPanel>
<Button.Content>
</Button>
The Binding on Path.Fill would still work in case you decide to move the Path to a ResourceDictionary.

StackPanel Collapsed and Visible on Button Click

I am trying to show one collapsed stackpanel on button click, but I'm having problems so I tried reverse my thoughts and I was able to collapse an visible stackpanel. But unfortunately I was unable to implement the behavior I want, show an collapsed stack panel on button click. To the code :D
XAML
<Button x:Name="sentButton" Content="Add Friend" Style="{DynamicResource FlatButtonStyle}" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Style="{DynamicResource stackCollapsed}" Visibility="Collapsed">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource MyTextBox}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Style="{DynamicResource FlatButtonStyle}" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
Styles
<!-- Style Collapsed-->
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="StackPanel.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
Instead of Button use ToggleButton and bind StackPanel.Visibility to ToggleButton.IsChecked property via BooleanToVisibilityConverter converter
<ToggleButton x:Name="sentButton" Content="Add Friend" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Visibility="{Binding ElementName=sentButton, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
where converter is defined as below
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</ResourceDictionary>
</Window.Resources>
The problem is the Visibility property in the <StackPanel> tab takes a higher precedence than anything set in a Style or Trigger, so the Trigger never gets applied. See the Dependency Property Precedence List for more details.
To fix your current solution, move the Visibliity property out of the <StackPanel> tag and into your Style, like this :
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<StackPanel Style="{DynamicResource stackCollapsed}">
...
</StackPanel>
That said, I would personally recommend something like a Toggle Button with the StackPanel.Visibility bound to the ToggleButton.IsChecked, like this answer suggests.
I solved set the Children to null
stackPanel.Children.Clear();
this work if you need to show / hide the panel the first time, it doesn't work if you need to do runtime
Simple as Stackpanel.Visibility = Visibility.Collapsed.

BooleanToVisibilityConverter with checkbox

I am trying to hide the grid, controlled by the checkbox. Currently, when I use the box nothing happens. I cannot figure out why. Everything I have found online is exactly what I have.
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<!--upper window..-->
<CheckBox x:Name="show" Grid.Row="1" IsChecked="False">Display Preview with Sliders?</CheckBox>
<Grid Grid.Row="1"
Visibility="{Binding ElementName=show, Path=isChecked, Converter={StaticResource BoolToVis}}">
<!--what I want to hide-->
</Grid>
</Grid>
It doesn't make any sense.
Property names are case sensitive. Replace isChecked with IsChecked in your binding.
Visibility="{Binding ElementName=show, Path=IsChecked,
Converter={StaticResource BoolToVis}}"
Try
Path=IsChecked
Even XAML is case-sensitive.
I advice to use a DataTrigger
<Style x:Key="CheckBoxStyle" TargetType="{x:Type CheckBoxStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=show,Path=IsChecked,}" Value="False">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>

Replace control template in toggle button on change state

I would like to create a flexible toggle button control. On toggle button "IsChecked" property "true", I would add two another buttons.
I have obtained this result by setting control template. But now how can I set default toggle button template (in this case toggle template is parrent) after button clicked? Toggle button should has "IsChecked" property set to false after undo.
XAML code:
<ToggleButton Content="Delete">
<ToggleButton.Style>
<Style>
<Setter Property="ToggleButton.Content" Value="Stops" />
<Style.Triggers>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter Property="ToggleButton.Template">
<Setter.Value>
<ControlTemplate>
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="24" />
</Grid.ColumnDefinitions>
<Button Command="{Binding ConditionalAcceptCommand}" Grid.Column="0">
<Image Source="pack://application:,,,/Images/check_mark24.png"/>
</Button>
<Button Grid.Column="1">
<Image Source="pack://application:,,,/Images/delete24.png"/>
</Button>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
Thanks

WPF C# DatePicker open calendar on click

I am adding a WPF DatePicker control to my form and it works fine. But I don't want the user to be able to type in a type in the 'Select a date' textbox. I want that to be readonly and when they click the textbox it just opens the calendar.
I wasn't sure if there was an option for this in the properties? I couldn't find anything...
<DatePicker HorizontalAlignment="Left" VerticalAlignment="Top">
<DatePicker.Resources>
<Style TargetType="DatePickerTextBox">
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="Text" Value=" "/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="IsEnabled" Value="False" />
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
</DatePicker.Resources>
</DatePicker>
In future you can use the WPF visualizer to see which child controls a top-level control is using (in this case DatePickerTextBox) and then apply a style and/or template to that type in the resources section like I've done here.
The answer of Mark Feldman is partially right, he had not answer to how clicking on the textbox gonna open the calendare popup!
You should hook the template of the DatePicker and enlarge the size of the button so it will overlap the textbox: then you are done, when you click on the textbox it's the button that get the event see below a part of the modified template of DatePicker:
<DatePickerTextBox Grid.Row="0" Grid.Column="0" x:Name="PART_TextBox" Focusable="{TemplateBinding Focusable}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
<Button Grid.Row="0" Grid.Column="0" x:Name="PART_Button" Foreground="{TemplateBinding Foreground}" Focusable="False" >
<Button.Template>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Background="Transparent"/>
<Button Grid.Column="1" HorizontalAlignment="Left" Foreground="{TemplateBinding Foreground}" Template="{StaticResource DropDownButtonTemplate}" VerticalAlignment="Top" Width="20" Margin="3,0,3,0" />
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
Dont forget to add the style of DatePickerTextBox described in the answer of Mark Feldman
You can open calendar this way :
<DatePicker Name="datePicker" Focusable="False">
<DatePicker.Resources>
<Style TargetType="DatePickerTextBox">
<EventSetter Event="MouseLeftButtonUp" Handler="OnMouseLeftButtonUp" />
</Style>
</DatePicker.Resources>
</DatePicker>
private void OnMouseLeftButtonUp(object sender, RoutedEventArgs e)
{
datePicker.IsDropDownOpen = true;
}

Categories

Resources