Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 控件模板情节提要,在同一模板内的其他控件中设置值_C#_Wpf_Controltemplate_Event Triggers - Fatal编程技术网

C# 控件模板情节提要,在同一模板内的其他控件中设置值

C# 控件模板情节提要,在同一模板内的其他控件中设置值,c#,wpf,controltemplate,event-triggers,C#,Wpf,Controltemplate,Event Triggers,我被要求围绕已经存在的DateTimePicker控件创建一个黑客程序。通常情况下,日期/时间选择器具有日历的美妙图像,然后旁边的文本框显示实际日期。用户可以单击图像并向其显示弹出式日历,选择后,日期将刷新到文本框区域 我遇到的问题是其他设计师不喜欢日历图形,只想要一个普通的文本框控件,但是如果用户双击打开一个弹出日历,获取日期并刷新它。我非常接近这一点,感谢S/O上的其他帮助 所以,描述我的控件模板,并保持简单(非自定义控件,除非我需要根据建议)。控件模板基于文本框控件。我们有一个文本框的PA

我被要求围绕已经存在的DateTimePicker控件创建一个黑客程序。通常情况下,日期/时间选择器具有日历的美妙图像,然后旁边的文本框显示实际日期。用户可以单击图像并向其显示弹出式日历,选择后,日期将刷新到文本框区域

我遇到的问题是其他设计师不喜欢日历图形,只想要一个普通的文本框控件,但是如果用户双击打开一个弹出日历,获取日期并刷新它。我非常接近这一点,感谢S/O上的其他帮助

所以,描述我的控件模板,并保持简单(非自定义控件,除非我需要根据建议)。控件模板基于文本框控件。我们有一个文本框的PART_ContentHost边框,然后是一个标准日历控件的弹出窗口

对于控件模板触发器,我有一个链接到ScrollViewer(文本框输入区域)的MouseDoubleClick事件。如果触发,将弹出窗口的等参线设置为true并显示日历。这个很好用

现在,完成它。如果用户从日历中选择日期,下一个触发器将关闭弹出窗口(IsOpen设置为false)。这也行得通

我的问题。我还希望在选择时获取所选日期,并将其ToString()日期表示形式放入ScrollViewer.Content(x:Name=“PART\u ContentHost”)中


我应该在这里放置什么来显示弹出日历的选定日期
已插入零件的内容\u ContentHost。。。

我确信这个问题可以通过几种方式解决,但在这些情况下,我通常会附加行为。但是,虽然情况不太正常,因为实现了控件的模板。在任何情况下,我认为附加行为都适合这种情况,在您的位置上,我会这样做

Attached Behavior是一个非常强大和方便的解决方案,完全满足MVVM模式,也可以在混合中使用(使用预定义接口)。Attached Behavior-是一个附加属性,它有一个事件处理程序来更改此属性,所有逻辑都在该处理程序中实现

<>在开始实现这个行为之前,我会考虑我对模板所做的一些修改。

我有点不明白为什么要使用as
PART\u ContentHost
ScrollViewer控件,可能会有几个日期,需要滚动显示。在WPF中,需要两个控件来显示内容:

  • 内容演示者
  • 内容控制
  • 这是他们的主要目标。第一个最轻的通常在模板中使用,但它不支持我们需要协调工作的事件,因此我选择了
    ContentControl
    。在为模板添加绑定属性的小东西上,设置为
    弹出窗口

    AllowsTransparency="True"
    VerticalOffset="4"
    HorizontalOffset="-5" 
    
    为了更好的可视化,现在转到行为的例子

    XAML

    <Window.Resources>
        <ControlTemplate x:Key="CTTextBox" TargetType="{x:Type TextBox}">
            <StackPanel AttachedBehaviors:SelectDateBehavior.IsEnabled="True"> <!-- Here is determined behaviour -->
                <Border x:Name="targetBorder" 
                        Width="{TemplateBinding Width}"
                        Height="{TemplateBinding Height}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Background="{TemplateBinding Background}"
                        TextBlock.Foreground="{TemplateBinding Foreground}"
                        SnapsToDevicePixels="True">
    
                    <ContentControl x:Name="ContentHost"
                                    Content="{TemplateBinding Text}"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                    Margin="4,0,0,0" />
                </Border>
    
                <Popup x:Name="PopCal" 
                       AllowsTransparency="True"
                       VerticalOffset="4"
                       HorizontalOffset="-5"
                       PlacementTarget="{Binding ElementName=ContentHost}">
    
                    <Calendar x:Name="ActualCalendar" />
                </Popup>
            </StackPanel>
        </ControlTemplate>
    
        <Style TargetType="{x:Type TextBox}" x:Key="STextBox">
            <Setter Property="FontFamily" Value="Arial" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="Height" Value="25" />
            <Setter Property="Width" Value="100" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="HorizontalContentAlignment" Value="Left" />
            <Setter Property="HorizontalAlignment" Value="Center" />       
            <Setter Property="CharacterCasing" Value="Upper" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="BorderBrush" Value="Gray" />
            <Setter Property="Background" Value="AliceBlue" />
            <Setter Property="Foreground" Value="Black" />
            <Setter Property="Template" Value="{StaticResource CTTextBox}" />
        </Style>
    </Window.Resources>
    
    <Grid>
        <TextBox Style="{StaticResource STextBox}"
                 Text="Select date" />
    </Grid>
    
    输出

    此处携带当前日期的设置:

    private static void calendarSelectedDatesChanged(object sender, SelectionChangedEventArgs e) 
    {
        // Skipped a few lines of code
        if (popup != null) 
        {
            contentHost.Content = calendar.SelectedDate;
            popup.IsOpen = false;
        }
    }
    
    一些注释

    首先,我们必须去掉EvenTrigger情节提要,因为在WPF动画中,设置值的优先级最高​​, 这意味着,如果我们在动画中设置值
    IsOpen
    ,则无法从其他来源(代码等)访问。因此,我将所有触发器/事件保留在行为一侧

    第二,解决方案与模板和控件的结构紧密相关。这意味着如果必须更改模板的结构,则必须更改模板和行为(可能不会太多)

    这个例子是可用的


    注意到了几个优点,我正在使用其他方法来定义类…@DRapp:我可以问一下,为什么您要寻找一个替代方法来定义类吗?对我来说,类行为是独立的,它只存在于一个名称空间中。我通过类来处理,因为在我们的类框架中还有一些其他潜在的附加元素at需要申请。我只是把它放在那里,根据你们这里的反馈,我想我已经完成了大部分。谢谢
    public class SelectDateBehavior
    {
        #region IsEnabled Dependency Property
    
        public static readonly DependencyProperty IsEnabledProperty;
    
        public static void SetIsEnabled(DependencyObject DepObject, bool value)
        {
            DepObject.SetValue(IsEnabledProperty, value);
        }
    
        public static bool GetIsEnabled(DependencyObject DepObject)
        {
            return (bool)DepObject.GetValue(IsEnabledProperty);
        }
    
        static SelectDateBehavior()
        {
            IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled",
                                                                typeof(bool),
                                                                typeof(SelectDateBehavior),
                                                                new UIPropertyMetadata(false, IsEnabledChanged));
        }
    
        #endregion
    
        #region IsEnabledChanged Handler
    
        private static void IsEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            Panel panel = sender as Panel;
    
            if (panel != null)
            {
                if (e.NewValue is bool && ((bool)e.NewValue) == true)
                {
                    panel.Loaded += new RoutedEventHandler(panelLoaded);
                }
                else
                {
                    panel.Loaded -= new RoutedEventHandler(panelLoaded);
                }
            }
        }
    
        #endregion
    
        #region Panel Loaded Handler
    
        private static void panelLoaded(object sender, RoutedEventArgs e) 
        {
            Panel panel = sender as Panel;
            Border border = panel.FindName("targetBorder") as Border;
            ContentControl contentHost = border.FindName("ContentHost") as ContentControl;
            Popup popup = panel.FindName("PopCal") as Popup;
    
            if (popup != null)
            {
                Calendar calendar = popup.FindName("ActualCalendar") as Calendar;                
                calendar.SelectedDatesChanged += new EventHandler<SelectionChangedEventArgs>(calendarSelectedDatesChanged);
            }
    
            if (contentHost != null)
            {
                contentHost.MouseDoubleClick += new MouseButtonEventHandler(contentHostMouseDoubleClick);
            }          
        }
    
        #endregion
    
        #region ContentHost MouseDoubleClick Handler
    
        private static void contentHostMouseDoubleClick(object sender, MouseButtonEventArgs e) 
        {
            ContentControl contentHost = sender as ContentControl;
            Border border = contentHost.Parent as Border;
            Panel panel = border.Parent as Panel;
            Popup popup = panel.FindName("PopCal") as Popup;
    
            if (popup != null) 
            {
                popup.IsOpen = true;
            }
        }
    
        #endregion
    
        #region Calendar SelectedDatesChanged Handler
    
        private static void calendarSelectedDatesChanged(object sender, SelectionChangedEventArgs e) 
        {
            Calendar calendar = sender as Calendar;
            Popup popup = calendar.Parent as Popup;
            Panel panel = popup.Parent as Panel;
            Border border = panel.FindName("targetBorder") as Border;
            ContentControl contentHost = border.FindName("ContentHost") as ContentControl;
    
            if (popup != null) 
            {
                contentHost.Content = calendar.SelectedDate;
                popup.IsOpen = false;
            }
        }
    
        #endregion
    }
    
    private static void calendarSelectedDatesChanged(object sender, SelectionChangedEventArgs e) 
    {
        // Skipped a few lines of code
        if (popup != null) 
        {
            contentHost.Content = calendar.SelectedDate;
            popup.IsOpen = false;
        }
    }