如何将一个控件放在源自XAML中另一个控件的标注中?

时间:2012-11-26 20:14:51

标签: silverlight xaml user-interface positioning

这是一个设置:我有一个带有数字值的文本框。根据要求,每当有人改变该值时,需要提供随附的评论。因此,视觉上必须有另一个注释文本框,应该显示在第一个文本框旁边。理想情况下,评论文本框需要放置在一个标注中,该标注来自值文本框并显示在右侧,它覆盖了下面的任何内容,就像在这张图片上一样:enter image description here

我知道如何在CSS和HTML中轻松完成。 我现在必须在Silverlight中做同样的事情。 不幸的是我不是很强大,所以我特别要问的是,如果有两个文本框使其中一个文本框出现在另一个文本框旁边(在右边覆盖它下面的任何控件),尽可能减少XAML和代码。 / p>

2 个答案:

答案 0 :(得分:0)

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

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

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

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

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

答案 1 :(得分:0)

好的,我最后写了自己的行为

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>