wpf 单击/触摸 PART_Textbox 时切换日期选择器日历

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20949608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:25:34  来源:igfitidea点击:

Toggle datepicker calendar when clicking/touching PART_Textbox

wpfxamldatepicker

提问by svh

I am writing a datepicker style in xaml The calendar popup is toggled by the calendar button next to the textbox of the datepicker I want the calendar also toggling when clicking/touching the textbox

我正在用 xaml 编写日期选择器样式日历弹出窗口由日期选择器文本框旁边的日历按钮切换我希望日历在单击/触摸文本框时也切换

When adding an event trigger to the datepicker style, the calendar toggles when touching the textbox, but only shows on a mouse click and stays open, when clicking/touching the datepicker calendar button, the calendar opens and closes immediately.

将事件触发器添加到日期选择器样式时,日历会在触摸文本框时切换,但仅在单击鼠标时显示并保持打开状态,当单击/触摸日期选择器日历按钮时,日历会立即打开和关闭。

<EventTrigger RoutedEvent="TextBox.PreviewMouseDown">
<EventTrigger.Actions>
    <BeginStoryboard x:Name="myBeginStoryboard">
        <Storyboard x:Name="myStoryboard">
            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsDropDownOpen">
                <DiscreteBooleanKeyFrame KeyTime="00:00:00"
                                         Value="True" />
            </BooleanAnimationUsingKeyFrames>
        </Storyboard>
    </BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>

My questions:

我的问题:

  • Is there a better way to achieve the desired behavior than using an event trigger?
  • How can the calendar show and hide when touching the control while the event trigger only sets the calendar visible?
  • Is it possible to assign the inverted "IsDropDownOpen" value to this property in xaml?
  • or is it possible to use a conditional statement (if?) in xaml to handle both hiding and showing?
  • 有没有比使用事件触发器更好的方法来实现所需的行为?
  • 当事件触发器仅设置日历可见时,如何在触摸控件时显示和隐藏日历?
  • 是否可以在 xaml 中将反转的“IsDropDownOpen”值分配给此属性?
  • 或者是否可以在 xaml 中使用条件语句(if?)来处理隐藏和显示?

采纳答案by Sheridan

Forget about the EventTriggerbecause it doesn't give you enough control. Instead of using that, just add a bool IsDropDownOpenproperty into your view model or code behind and bind it to the DatePicker.IsDropDownOpenproperty. This way, you are free to open and close the Popupanytime you want and/or in response to any single, or collection of events. For example:

忘记EventTrigger它,因为它没有给你足够的控制权。而不是使用它,只需将一个bool IsDropDownOpen属性添加到您的视图模型或后面的代码中并将其绑定到该DatePicker.IsDropDownOpen属性。通过这种方式,您可以Popup随时和/或响应任何单个或事件集合自由地打开和关闭。例如:

public void TextBoxPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    IsDropDownOpen = true;
}

private void TextBoxPreviewTouchDown(object sender, TouchEventArgs e)
{
    IsDropDownOpen = true;
}

private void DatePickerSelectedDateChanged(object sender, SelectionChangedEventArgs e)
{
    IsDropDownOpen = false;
}

回答by SWilko

Think you're using the wrong event. You need to drill down into the PART_TextBox event PreviewMouseLeftButtonUp in your DatePicker. Code below gives your DatePicker a name DateYou will need to add this logic for any other events you require.

认为您使用了错误的事件。您需要深入了解 DatePicker 中的 PART_TextBox 事件 PreviewMouseLeftButtonUp。下面的代码为您的 DatePicker 提供了一个名称Date您需要为您需要的任何其他事件添加此逻辑。

NB This would also be more elegant if handled using MVVM practises

注意如果使用 MVVM 实践处理,这也会更优雅

    private void PART_TextBox_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        if (Date.IsDropDownOpen)
            Date.IsDropDownOpen = false;
        else
            Date.IsDropDownOpen = true;
    }

回答by haps

Use Blend to make a control template, "DatePickerControlTemplate1" for the datepicker and then find x:Name="PART_TextBox". There you can EventTriggers on MouseEnter and MouseLeftButtonDown or use an InputBinding on LeftClick

使用 Blend 制作一个控件模板,日期选择器的“DatePickerControlTemplate1”,然后找到 x:Name="PART_TextBox"。您可以在 MouseEnter 和 MouseLeftButtonDown 上使用 EventTriggers 或在 LeftClick 上使用 InputBinding

                <DatePickerTextBox x:Name="PART_TextBox" Grid.Column="0" Focusable="{TemplateBinding Focusable}" HorizontalContentAlignment="Stretch" Grid.Row="0" VerticalContentAlignment="Stretch" Style="{StaticResource BlueTextBoxStyle}">
                    <TextBox.InputBindings>
                        <MouseBinding Gesture="LeftClick" Command="{Binding ShowCalendarCommand}" />
                    </TextBox.InputBindings>
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseEnter">
                            <cmd:EventToCommand Command="{Binding ShowCalendarCommand}" PassEventArgsToCommand="True" />
                        </i:EventTrigger>
                        <i:EventTrigger EventName="MouseLeftButtonDown">
                            <cmd:EventToCommand Command="{Binding ShowCalendarCommand}" PassEventArgsToCommand="True" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                 </DatePickerTextBox>

MVVM XAML:

MVVM XAML:

    <DatePicker IsDropDownOpen="{Binding ShowCalendar}" Template="{StaticResource DatePickerControlTemplate1}"/>

ViewModel:

视图模型:

    private bool _showCalendar = false;
    public bool ShowCalendar
    {
        get
        {
            return _showCalendar;
        }
        set
        {
            if (_showCalendar != value)
            {
                _showCalendar = value;
                RaisePropertyChanged(() => ShowCalendar);
            }
        }
    }

    public RelayCommand ShowCalendarCommand { get; private set; }

    ShowCalendarCommand = new RelayCommand(ExecuteShowCalendarCommand);

    private void ExecuteShowCalendarCommand()
    {
        ShowCalendar = true;
    }

Unfortunately, since the Calendar doesn't have focus it will close unless you set StaysOpen="true" in the DatePicker Control Template for the Popup

不幸的是,由于日历没有焦点,除非您在弹出窗口的 DatePicker 控件模板中设置 StaysOpen="true",否则它将关闭

"PART_Popup":

“PART_Popup”:

    <Popup x:Name="PART_Popup" AllowsTransparency="True" Placement="Bottom" StaysOpen="true" />