0

我正在尝试实现 Datepicker 控件的 Outlook 样式的功能。

我有一个文本框,它应用的样式看起来与 Outlook 中的完全相同,但我的问题是弹出窗口有一个日历和两个按钮,即 Today 和 none。只要单击 Today 按钮,文本框值应设置为今天的日期,如果我单击无,文本框值必须设置为无。

我使用的风格是

         <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>

任何帮助或想法来实现这一点将不胜感激。

4

2 回答 2

1

如果你有一个自定义控件,那么我建议你重写 OnApplyTemplate 方法并使用 GetTemplatedChild 来查找按钮,订阅它的点击,就是这样,除非你必须找到 TextBox 并在处理程序中设置它的 Text。

如果由于某种原因你不能这样做,这里有一个小技巧,如何让它仍然有效

看看这个:

<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>
于 2013-11-07T07:55:36.643 回答
0

将事件处理程序附加到 a 中定义的元素的一般方法ControlTemplate是覆盖该FrameworkElement.OnApplyTemplate方法:

public override void OnApplyTemplate()
{
    Button button = (Button)Template.FindName("btnToday", this);
    button.Click += SomeClickHandler;
}

更新>>>

我在上面使用this(作为第二个输入参数)的地方,它代表templatedParent输入参数。正确的值将取决于应用于哪个对象Template......在这种情况下,我相信它应该是this对象。

更新 2 >>>

抱歉,我以为你可以编写一个Click事件处理程序。这是一个:

private void SomeClickHandler(object sender, RoutedEventArgs e)
{
    // Set your DateTime here
}
于 2013-11-07T09:31:37.617 回答