Reputation: 159
am trying to achieve the functionality of Outlook style of Datepicker control.
I have a textbox which am applying a style which looks exactly same as in Outlook but my problem is popup having a calendar and two button as Today and none.As soon as click on Today button the textbox value should set to todays date and if i click None the text box value has to set as none.
The style i have used is
<Style x:Key="tbCalendarStyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border BorderThickness="1" BorderBrush="DarkGray">
<ScrollViewer x:Name="PART_ContentHost" />
</Border>
<ToggleButton Template="{StaticResource IconButton}"
MaxHeight="21"
Margin="-1,0,0,0"
Name="PopUpImageButton"
Focusable="False"
IsChecked="False">
<ToggleButton.Content>
<Path x:Name="btnArrow4" Margin="4" VerticalAlignment="Center" Width="10" Fill="Black" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/>
</ToggleButton.Content>
</ToggleButton>
<Popup IsOpen="{Binding Path=IsChecked, ElementName=PopUpImageButton, Mode=TwoWay}" x:Name="CustomPopup" Margin="0,-1,0,0" PopupAnimation="Fade" StaysOpen="False">
<StackPanel Orientation="Vertical" removed="BlueViolet">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="164"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Calendar Grid.Row="0" Margin="0,-1,0,0" x:Name="CalDisplay"
SelectedDate="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Text, Mode=TwoWay, Converter={StaticResource calendarConverter}}"
Focusable="False"
DisplayDate="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Text, Mode=OneWay, Converter={StaticResource calendarConverter}}"
>
<Control.Triggers>
<EventTrigger RoutedEvent="Calendar.SelectedDatesChanged">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="PopUpImageButton" Storyboard.TargetProperty="IsChecked">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False"></DiscreteBooleanKeyFrame>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Control.Triggers>
</Calendar>
</Grid>
<StackPanel Orientation="Horizontal" FlowDirection="LeftToRight">
<Button Content="Today" Grid.Row="1" Width="50" VerticalAlignment="Center" Margin="20 0 0 10" Name="btnToday">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
// what should i do to achieve the above logic
</EventTrigger>
</Button.Triggers>
</Button>
<Button Content="None" Grid.Row="1" Margin="30 0 0 10" Width="50" VerticalAlignment="Center" Name="btnNone">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</StackPanel>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Visibility" TargetName="PopUpImageButton" Value="Visible" />
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="Visibility" TargetName="PopUpImageButton" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Any help or idea to achieve this would be highly appreciated.
Upvotes: 0
Views: 2448
Reputation: 69959
The general way to attach event handlers to elements that are defined within a ControlTemplate
is to override the FrameworkElement.OnApplyTemplate
method:
public override void OnApplyTemplate()
{
Button button = (Button)Template.FindName("btnToday", this);
button.Click += SomeClickHandler;
}
UPDATE >>>
Where I have used this
(as the second input parameter) above, it stands for the templatedParent
input parameter. The correct value will depend on which object the Template
was applied to... in this case, I believe that it should be the this
object.
UPDATE 2 >>>
Sorry, I thought that you could write a Click
event handler. Here is one:
private void SomeClickHandler(object sender, RoutedEventArgs e)
{
// Set your DateTime here
}
Upvotes: 0
Reputation: 8791
If you have a custom control then I suggest you to override the method OnApplyTemplate and use GetTemplatedChild to find the Button, subscribe to its click and thats it except you will have to find the TextBox and set its Text inside the handler.
If you cannot do so for whatever reason here is a small trick how to make it still work
Take a look at this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WPFControls.Generic"
xmlns:local="clr-namespace:WPFControls">
<Style TargetType="{x:Type local:MyChildControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyChildControl}">
<Border Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
<StackPanel>
<TextBox x:Name="tbx1"/>
<Button Content="{TemplateBinding Content}" Click="OnClick"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
....
And this is the code behind for Generic.xaml dictionary.
public partial class Generic
{
public void OnClick(object sender, RoutedEventArgs e)
{
MyChildControl control = FindAncestor<MyChildControl>((DependencyObject)sender);
TextBox tbx = control.Template.FindName("tbx1", control) as TextBox;
tbx.Text = "It works!";
}
public static T FindAncestor<T>(DependencyObject current) where T : DependencyObject
{
current = VisualTreeHelper.GetParent(current);
while (current != null)
{
if (current is T)
{
return (T)current;
}
current = VisualTreeHelper.GetParent(current);
};
return null;
}
}
This is mine MainWindow.xaml:
<Window ....>
<Grid>
<local:MyChildControl Content="Click me!"/>
</Grid>
</Window>
Upvotes: 1