我正在尝试实现Datepicker控件的Outlook样式的功能。
我有一个文本框,它正在应用一个与Outlook完全相同的样式,但我的问题是弹出一个日历和两个按钮为今天和无。只要点击今天按钮,文本框值应设置为今天的日期如果我单击“无”,则文本框值必须设置为“无”。
我使用的风格是
<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>
任何有助于实现这一目标的帮助或想法都将受到高度赞赏。
答案 0 :(得分:1)
如果你有一个自定义控件,那么我建议你覆盖OnApplyTemplate方法,并使用GetTemplatedChild找到Button,订阅它的点击就可以了,除非你必须找到TextBox并在处理程序中设置它的Text。 / p>
如果由于某种原因你不能这样做,这是一个小技巧,如何让它仍然有用
看看这个:
<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>
....
这是Generic.xaml词典背后的代码。
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;
}
}
这是我的MainWindow.xaml:
<Window ....>
<Grid>
<local:MyChildControl Content="Click me!"/>
</Grid>
</Window>
答案 1 :(得分:0)
将事件处理程序附加到ControlTemplate
中定义的元素的一般方法是覆盖FrameworkElement.OnApplyTemplate
方法:
public override void OnApplyTemplate()
{
Button button = (Button)Template.FindName("btnToday", this);
button.Click += SomeClickHandler;
}
更新&gt;&gt;&gt;
我在上面使用this
(作为第二个输入参数),它代表templatedParent
输入参数。正确的值取决于Template
应用于哪个对象...在这种情况下,我认为它应该是this
对象。
更新2&gt;&gt;&gt;
抱歉,我认为你可以写一个Click
事件处理程序。这是一个:
private void SomeClickHandler(object sender, RoutedEventArgs e)
{
// Set your DateTime here
}