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
Related
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>
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.
I'm working on making a simple tic-tac-toe game to familiarize myself with WPF, due to the amount of time it's been since I've used the format. I've been trying to disable the button, to prevent people from choosing the same square, after the content has been set to X or O. Here is a sample of my XAML code for the buttons:
<Button Name="btmRight" Margin="10 10 10 10" Grid.Column="2" Grid.Row="2" FontSize="128">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="1"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
The buttons are enabled by default. I then use some simple C# code to disable the button, and set the content to X or O depending on the turn. However, despite the style trigger being in each button, the format is never changed. Something I might explore is putting a conditional in the code, to not change anything with the buttons if they have content, rather than disabling the button when it's clicked. Here is a sample of what I'm using for the C#:
mid.Click += (sender, e) =>
{
mid.Content = mark;
TurnSwap();
mid.IsEnabled = false;
IsComplete();
};
"mark" is a String that is set depending on the turn. The content is set to the mark value, which then rotates immediately after the content is set. The button is then disabled, and the game checks to see if someone has won yet. If I were to go with the option of manually disabling the button, I would surround that C# code in a conditional, to check if the content = "", which it is by default. I feel this option is a bit lazy, and I would like to learn the WPF solution for the concepts alone.
The following code is just a sample based on your question. I does not have tic-tac-toe game logic implemented.
It demonstraits how to implement common style to button and also implmentation of common ClickEvent.
You can use it and change it as per you need.
XAML
<Window x:Class="WPFTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFTest"
mc:Ignorable="d"
Title="TestWPF" Height="300" Width="400"
WindowStyle="None" WindowStartupLocation="CenterScreen">
<Window.Resources>
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Background" Value="MediumAquamarine" />
<Setter Property="Foreground" Value="MediumBlue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter x:Name="MyContentPresenter"
Content="{TemplateBinding Content}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="1"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="btn1" Grid.Row="0" Grid.Column="0" Style="{StaticResource buttonStyle}" Click="btn_Click"/>
<Button x:Name="btn2" Grid.Row="0" Grid.Column="1" Style="{StaticResource buttonStyle}" Click="btn_Click"/>
<Button x:Name="btn3" Grid.Row="0" Grid.Column="2" Style="{StaticResource buttonStyle}" Click="btn_Click"/>
<Button x:Name="btn4" Grid.Row="1" Grid.Column="0" Style="{StaticResource buttonStyle}" Click="btn_Click"/>
<Button x:Name="btn5" Grid.Row="1" Grid.Column="1" Style="{StaticResource buttonStyle}" Click="btn_Click"/>
<Button x:Name="btn6" Grid.Row="1" Grid.Column="2" Style="{StaticResource buttonStyle}" Click="btn_Click"/>
<Button x:Name="btn7" Grid.Row="2" Grid.Column="0" Style="{StaticResource buttonStyle}" Click="btn_Click"/>
<Button x:Name="btn8" Grid.Row="2" Grid.Column="1" Style="{StaticResource buttonStyle}" Click="btn_Click"/>
<Button x:Name="btn9" Grid.Row="2" Grid.Column="2" Style="{StaticResource buttonStyle}" Click="btn_Click"/>
</Grid>
</Window>
CS
using System;
using System.Windows;
using System.Windows.Controls;
namespace WPFTest
{
public partial class MainWindow : Window
{
string sign = "X";
public MainWindow()
{
InitializeComponent();
}
private void btn_Click(object sender, RoutedEventArgs e)
{
try
{
Button currentButton = sender as Button;
currentButton.Content = sign;
currentButton.IsEnabled = false;
swapSign();
}
catch (Exception ex)
{
}
}
private void swapSign()
{
if (sign == "X")
sign = "O";
else
sign = "X";
}
}
}
UPDATE-1
I changed the style in XAML. Check above. One thing to note here is that you have to set Background and Foreground properties of Button Style like I set.
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;
}
How can I set Visibility="Visible" for the Button inside the Control Template when the IsSendBtnVisible property in the code-behind is true?
Here's my WPF page:
<Page
x:Class="CardViewPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CardViewPage">
<Grid Name="content" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DocumentViewer Margin="0" Grid.Row="0" Name="documentViewer" />
</Grid>
</Page>
Here's my Custom Template for the document viewer on this page:
<Style TargetType="{x:Type DocumentViewer}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DocumentViewer}">
...
<Button
Click="btnSendToServer_Click"
Width="25"
Height="25"
Visibility="Collapsed" />
...
</ControlTemplate>
</Setter>
...
</Style>
U need to declare DependancyProperty for ur DocumentViewer and use TemplateBinding in xaml ControlTemplate (UrProperty for example)
<ControlTemplate TargetType="{x:Type DocumentViewer}">
...
<Button Click="btnSendToServer_Click"
Width="25"
Height="25"
Visibility="{TemplateBinding UrProperty}"
/>
...
</ControlTemplate>
I suggest you to use data triggers to achieve this...
<Button
Click="btnSendToServer_Click"
Width="25"
Height="25">
<Button.Style>
<Style>
<Setter Property="Button.Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSendBtnVisible}" Value="True">
<Setter Property="Button.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Make sure to set visibility to collapsed in the style but not in the button properties..
Note: Binding for data trigger may change depending on your data context
Dima Martovoi,bathineni - thanks for replies.
Dima Martovoi, i think inherit from DocumentViewer is to hard for this small problem.
I tried to use variant with DataTrigger from bathineni's solution, but it's not works. Don't know, why.
Problem was solved using next binding:
<Button
Visibility="{Binding RelativeSource={RelativeSource AncestorType=Page},Path=SendToServerVisiblity}">
</Button>
where
public Visibility SendToServerVisiblity
{
get
{
if (IsOnlineMode)
return Visibility.Visible;
return Visibility.Collapsed;
}
}
in page code-behind