【问题标题】:How can I place one control in a callout that orginates from another control in XAML?如何将一个控件放置在源自 XAML 中另一个控件的标注中?
【发布时间】:2012-11-26 20:14:51
【问题描述】:

这是一个设置:我有一个带有数字值的文本框。根据要求,每次任何人更改该值时都需要提供随附的评论。所以在视觉上必须有另一个文本框用于应该显示在第一个旁边的评论。理想情况下,注释文本框需要放置在源自值文本框的标注中,并显示在其右侧,覆盖其下方的任何内容,就像这张图片一样:

我知道如何在 CSS 和 HTML 中轻松做到这一点。 我现在必须在 Silverlight 中做同样的事情。 不幸的是,我在这方面不是很强大,所以我特别要问的是如何让 2 个文本框使其中一个出现在另一个旁边(在右侧覆盖它下面的任何控件),并尽可能少地使用 XAML 和代码。

【问题讨论】:

    标签: silverlight xaml user-interface positioning


    【解决方案1】:

    使用ToolTip,并设置Placement 使其显示在右侧。在 XAML 中,您可以将 ToolTip 模板化为您想要的外观,即使这意味着模仿 TextBox 的外观。

    这是ToolTip 的目的,我强烈认为您应该始终为正确的工作使用正确的工具。 :)

    我希望这会有所帮助。如果您需要代码示例,请告诉我们。

    编辑:添加了以下代码示例:

        <TextBox ToolTipService.Placement="Right">
            <ToolTipService.ToolTip>
                <TextBox Text="{Binding CalloutText, Mode=OneWay}" IsReadOnly="True"/>
            </ToolTipService.ToolTip>
        </TextBox>
    

    【讨论】:

    • 如何控制它的位置?
    • 您可以使用ToolTipService.Placement AttachedProperty 设置位置。您也可以使用ToolTipService.VerticalOffsetToolTipService.HorizontalOffset 来调整定位。如果您需要更多控制权,请考虑使用ToolTipService.PlacementRectangle
    • 谢谢,但我怎样才能让工具提示保持不变?一旦所有者控制失去焦点,我就会消失。
    • 使用ToolTipService.ShowDuration AttachedProperty 调整它保持活动的时间长度。
    • 好吧,只要值 texbox 或评论 texbox 保持焦点,我就需要它保持不变。所以这不是我事先知道的绝对时间范围。
    【解决方案2】:

    好的,我最终写下了自己的行为

    namespace MyNamespace
    {
        public class CommentBehavior : Behavior<TextBox>
        {
            private readonly TimeSpan howLongWeWaitBeforePopupCloses = TimeSpan.FromMilliseconds(200);
    
            private DispatcherTimer popupClosingTimer;
            public static DependencyProperty PopupProperty = DependencyProperty.Register("Popup", typeof(Popup), typeof(CommentBehavior), new PropertyMetadata(null));
    
            public Popup Popup
            {
                get { return (Popup)this.GetValue(PopupProperty); }
                set { this.SetValue(PopupProperty, value); }
            }
    
            protected override void OnAttached()
            {
                this.popupClosingTimer = new DispatcherTimer();
                this.popupClosingTimer.Stop();
                this.popupClosingTimer.Interval = howLongWeWaitBeforePopupCloses;
                this.popupClosingTimer.Tick += this.ClosePopup;
                this.AssociatedObject.GotFocus += this.GotFocus;
                this.AssociatedObject.LostFocus += this.LostFocus;
                this.Popup.Child.GotFocus += PopupChild_GotFocus;
                this.Popup.Child.LostFocus += PopupChild_LostFocus;
            }
    
            private void PopupChild_LostFocus(object sender, RoutedEventArgs e)
            {
                this.popupClosingTimer.Start();
            }
    
            private void PopupChild_GotFocus(object sender, RoutedEventArgs e)
            {
                this.popupClosingTimer.Stop();
            }
    
            protected override void OnDetaching()
            {
                this.AssociatedObject.GotFocus -= this.GotFocus;
                this.AssociatedObject.LostFocus -= this.LostFocus;
                this.Popup.GotFocus -= PopupChild_GotFocus;
                this.popupClosingTimer.Tick -= this.ClosePopup;
                this.popupClosingTimer = null;
            }
    
            private void ClosePopup(object sender, EventArgs e)
            {
                this.Popup.IsOpen = false;
                this.popupClosingTimer.Stop();
            }
    
            protected void GotFocus(object sender, RoutedEventArgs e)
            {
                this.popupClosingTimer.Stop();
                this.Popup.IsOpen = true;
                var at = this.CalculatePopupPosition();
                this.Popup.HorizontalOffset = at.X;
                this.Popup.VerticalOffset = at.Y;
            }
    
            private Point CalculatePopupPosition()
            {
                var owner = this.AssociatedObject;
                var transformation = owner.TransformToVisual(Application.Current.RootVisual);
                var at = transformation.Transform(new Point(owner.ActualWidth, 0));
                return at;
            }
    
            protected void LostFocus(object sender, RoutedEventArgs e)
            {
                this.popupClosingTimer.Start();
            }
        }
    }
    

    还有下面的 XAML

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
    
        <StackPanel Grid.Row="0" Background="Red">
            <TextBox Width="200" Text="0.01">
                <i:Interaction.Behaviors>
                    <local:CommentBehavior>
                        <local:CommentBehavior.Popup>
                            <Popup>
                                <TextBox Text="Comment" />
                            </Popup>
                        </local:CommentBehavior.Popup>
                    </local:CommentBehavior>
                </i:Interaction.Behaviors>
            </TextBox>
        </StackPanel>
    
    </Grid>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-23
      • 1970-01-01
      • 2010-11-14
      • 1970-01-01
      • 2016-01-04
      • 2014-12-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多