Silverlight Popup UserControl - 工作一次,然后崩溃

时间:2009-03-18 06:19:40

标签: silverlight user-controls

我正在制作Silverlight2 UserControl以模拟WinForms MessageBox的基本功能。我正在关注Shawn WildermuthJohn Papa's个例子。

编译好,我用一个按钮将用户控件添加到我的应用程序以显示弹出窗口。这样工作 - 弹出窗口出现,您可以单击按钮关闭它然后关闭。你可以多次这样做。

如果包含“MessageBox”的UserControl已关闭且创建了新的UserControl,则会出现此问题。如果您尝试在新实例上打开弹出窗口,则会抛出异常:

Unhandled Error in Silverlight 2 Application
Code: 4004
Category: ManagedRuntimeError
Message: System.ArgumentException: Value does not fall within the expected range.
  at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
  at MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement element, Size availableSize)
  at System.Windows.FrameworkElement.MeasureOverride(Size availableSize)
  ...
  (stack trace doesnt go as far as any of my code)

控件的代码位于帖子的底部。如果你想运行它,我已经制作了testbench project to demonstrate the problem.测试平台有屏幕上的说明,告诉你如何重现这个问题。

这让我疯了,所以任何帮助或指示都会非常感激。

以下是PopupMessage用户控件的代码:

<UserControl x:Class="SilverlightPopupControlTest.PopupMessage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows" 
    >
    <Grid x:Name="LayoutRoot">

        <vsm:VisualStateManager.VisualStateGroups>
            <vsm:VisualStateGroup x:Name="PopupState" CurrentStateChanged="PopupState_CurrentStateChanged">
                <vsm:VisualStateGroup.Transitions>
                    <vsm:VisualTransition GeneratedDuration="00:00:00.2000000"/>
                    <vsm:VisualTransition GeneratedDuration="00:00:00.2000000" To="PopupStateOpened"/>
                    <vsm:VisualTransition GeneratedDuration="00:00:00.2000000" To="PopupStateClosed"/>
                </vsm:VisualStateGroup.Transitions>
                <vsm:VisualState x:Name="PopupStateClosed">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="PopupFillGrid" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                            <SplineColorKeyFrame KeyTime="00:00:00" Value="#00FFFFFF"/>
                        </ColorAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.Opacity)">
                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </vsm:VisualState>
                <vsm:VisualState x:Name="PopupStateOpened">
                    <Storyboard>
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="PopupFillGrid" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                            <SplineColorKeyFrame KeyTime="00:00:00" Value="#BFFFFFFF"/>
                        </ColorAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.Opacity)">
                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </vsm:VisualState>
            </vsm:VisualStateGroup>
        </vsm:VisualStateManager.VisualStateGroups>

        <Popup x:Name="PopupControl">
            <Grid x:Name="PopupFillGrid">
                <Grid.Background>
                    <SolidColorBrush Color="#00ffffff"/>
                </Grid.Background>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>

                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>

                <Border Grid.Row="1" Grid.Column="1" RenderTransformOrigin="0.5,0.5" x:Name="border" Opacity="0" >
                    <Border.RenderTransform>
                        <TransformGroup>
                            <ScaleTransform ScaleX="0.5" ScaleY="0.5"/>
                            <SkewTransform/>
                            <RotateTransform/>
                            <TranslateTransform/>
                        </TransformGroup>
                    </Border.RenderTransform>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="40"/>
                        </Grid.RowDefinitions>

                        <ContentPresenter x:Name="PopupContentPresenter"/>

                        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
                            <Button x:Name="Button1" Click="Button1_Click" Margin="4" MinWidth="80">
                                <ContentPresenter x:Name="Button1ContentPresenter"/>
                            </Button>
                            <Button x:Name="Button2" Click="Button2_Click" Margin="4" MinWidth="80">
                                <ContentPresenter x:Name="Button2ContentPresenter"/>
                            </Button>
                            <Button x:Name="Button3" Click="Button3_Click"  Margin="4" MinWidth="80">
                                <ContentPresenter x:Name="Button3ContentPresenter"/>
                            </Button>
                        </StackPanel>
                    </Grid>
                </Border>
            </Grid>
        </Popup>
    </Grid>
</UserControl>

及其代码隐藏

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightPopupControlTest
{
    public partial class PopupMessage : UserControl
    {
        #region PopupContent Dependency Property
        public UIElement PopupContent
        {
            get { return (UIElement)GetValue(PopupContentProperty); }
            set { SetValue(PopupContentProperty, value); }
        }
        public static readonly DependencyProperty PopupContentProperty = DependencyProperty.Register(
            "PopupContent", typeof(UIElement), typeof(PopupMessage), new PropertyMetadata(PopupContentChanged));

        private static void PopupContentChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ((PopupMessage)o).OnPopupContentChanged((UIElement)e.OldValue, (UIElement)e.NewValue);
        }

        private void OnPopupContentChanged(UIElement oldValue, UIElement newValue)
        {
            this.PopupContentPresenter.Content = newValue;
        }
        #endregion
        #region Button1Visibility Dependency Property
        public Visibility Button1Visibility
        {
            get { return (Visibility)GetValue(Button1VisibilityProperty); }
            set { SetValue(Button1VisibilityProperty, value); }
        }
        public static readonly DependencyProperty Button1VisibilityProperty = DependencyProperty.Register(
            "Button1Visibility", typeof(Visibility), typeof(PopupMessage), new PropertyMetadata(Button1VisibilityChanged));


        private static void Button1VisibilityChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ((PopupMessage)o).OnButton1VisibilityChanged((Visibility)e.OldValue, (Visibility)e.NewValue);
        }

        private void OnButton1VisibilityChanged(Visibility oldValue, Visibility newValue)
        {
            this.Button1.Visibility = newValue;
        }
        #endregion
        #region Button2Visibility Dependency Property
        public Visibility Button2Visibility
        {
            get { return (Visibility)GetValue(Button2VisibilityProperty); }
            set { SetValue(Button2VisibilityProperty, value); }
        }
        public static readonly DependencyProperty Button2VisibilityProperty = DependencyProperty.Register(
            "Button2Visibility", typeof(Visibility), typeof(PopupMessage), new PropertyMetadata(Button2VisibilityChanged));

        private static void Button2VisibilityChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ((PopupMessage)o).OnButton2VisibilityChanged((Visibility)e.OldValue, (Visibility)e.NewValue);
        }

        private void OnButton2VisibilityChanged(Visibility oldValue, Visibility newValue)
        {
            this.Button2.Visibility = newValue;
        }
        #endregion
        #region Button3Visibility Dependency Property
        public Visibility Button3Visibility
        {
            get { return (Visibility)GetValue(Button3VisibilityProperty); }
            set { SetValue(Button3VisibilityProperty, value); }
        }
        public static readonly DependencyProperty Button3VisibilityProperty = DependencyProperty.Register(
            "Button3Visibility", typeof(Visibility), typeof(PopupMessage), new PropertyMetadata(Button3VisibilityChanged));


        private static void Button3VisibilityChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ((PopupMessage)o).OnButton3VisibilityChanged((Visibility)e.OldValue, (Visibility)e.NewValue);
        }

        private void OnButton3VisibilityChanged(Visibility oldValue, Visibility newValue)
        {
            this.Button3.Visibility = newValue;
        }
        #endregion
        #region Button1Content Dependency Property
        public UIElement Button1Content
        {
            get { return (UIElement)GetValue(Button1ContentProperty); }
            set { SetValue(Button1ContentProperty, value); }
        }
        public static readonly DependencyProperty Button1ContentProperty = DependencyProperty.Register(
            "Button1Content", typeof(UIElement), typeof(PopupMessage), new PropertyMetadata(Button1ContentChanged));

        private static void Button1ContentChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ((PopupMessage)o).OnButton1ContentChanged((UIElement)e.OldValue, (UIElement)e.NewValue);
        }

        private void OnButton1ContentChanged(UIElement oldValue, UIElement newValue)
        {
            this.Button1ContentPresenter.Content = newValue;
        }
        #endregion
        #region Button2Content Dependency Property
        public UIElement Button2Content
        {
            get { return (UIElement)GetValue(Button2ContentProperty); }
            set { SetValue(Button2ContentProperty, value); }
        }
        public static readonly DependencyProperty Button2ContentProperty = DependencyProperty.Register(
            "Button2Content", typeof(UIElement), typeof(PopupMessage), new PropertyMetadata(Button2ContentChanged));


        private static void Button2ContentChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ((PopupMessage)o).OnButton2ContentChanged((UIElement)e.OldValue, (UIElement)e.NewValue);
        }

        private void OnButton2ContentChanged(UIElement oldValue, UIElement newValue)
        {
            this.Button2ContentPresenter.Content = newValue;
        }
        #endregion
        #region Button3Content Dependency Property
        public UIElement Button3Content
        {
            get { return (UIElement)GetValue(Button3ContentProperty); }
            set { SetValue(Button3ContentProperty, value); }
        }
        public static readonly DependencyProperty Button3ContentProperty = DependencyProperty.Register(
            "Button3Content", typeof(UIElement), typeof(PopupMessage), new PropertyMetadata(Button3ContentChanged));

        private static void Button3ContentChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ((PopupMessage)o).OnButton3ContentChanged((UIElement)e.OldValue, (UIElement)e.NewValue);
        }

        private void OnButton3ContentChanged(UIElement oldValue, UIElement newValue)
        {
            this.Button3ContentPresenter.Content = newValue;
        }
        #endregion

        public enum PopupMessageResult
        {
            Unknown=0,
            Button1=1,
            Button2,
            Button3
        }

        #region PopupMessageClosed Event
        public class PopupMessageClosedEventArgs : EventArgs
        {
            public PopupMessage.PopupMessageResult Result { get; set; }

            public PopupMessageClosedEventArgs()
            {
            }

            public PopupMessageClosedEventArgs(PopupMessage.PopupMessageResult _Result)
            {
                this.Result = _Result;
            }

        }

        public delegate void PopupMessageClosedEventHandler(object sender, PopupMessageClosedEventArgs e);

        public event PopupMessageClosedEventHandler PopupMessageClosed;

        protected virtual void OnPopupMessageClosed(PopupMessageClosedEventArgs e)
        {
            if (PopupMessageClosed != null)
            {
                PopupMessageClosed(this, e);
            }
        }
        #endregion

        private PopupMessageResult m_Result = PopupMessageResult.Unknown;
        public PopupMessageResult Result
        {
            get { return m_Result; }
            set { m_Result = value; }
        }

        private FrameworkElement m_HostControl = null;
        public FrameworkElement HostControl
        {
            get { return m_HostControl; }
            set { m_HostControl = value; }
        }

        public PopupMessage()
        {
            InitializeComponent();

            this.Button1Visibility = Visibility.Collapsed;
            this.Button2Visibility = Visibility.Collapsed;
            this.Button3Visibility = Visibility.Collapsed;

            VisualStateManager.GoToState(this, "PopupStateClosed", false);
        }

        private void Close()
        {
            VisualStateManager.GoToState(this, "PopupStateClosed", true);
        }

        public void Show()
        {

            this.PopupControl.IsOpen = true;
            this.Visibility = Visibility.Visible;
            this.TabNavigation = KeyboardNavigationMode.Cycle;
            this.Button1.Focus();

            VisualStateManager.GoToState(this, "PopupStateOpened", true);
        }

        void PopupState_CurrentStateChanged(object sender, VisualStateChangedEventArgs e)
        {
            if (e.NewState.Name == "PopupStateClosed")
            {
                this.PopupControl.IsOpen = false;
                this.Visibility = Visibility.Collapsed;

                this.OnPopupMessageClosed(new PopupMessageClosedEventArgs(this.Result));
            }
        }

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            this.Result = PopupMessageResult.Button1;
            this.Close();
        }

        private void Button2_Click(object sender, RoutedEventArgs e)
        {
            this.Result = PopupMessageResult.Button2;
            this.Close();
        }

        private void Button3_Click(object sender, RoutedEventArgs e)
        {
            this.Result = PopupMessageResult.Button3;
            this.Close();
        }
    }
}

2 个答案:

答案 0 :(得分:4)

您收到的实际错误消息如下:

alt text

如果您重构Page.xaml.cs看起来如下,它将修复您的错误:

public partial class Page : UserControl
{
    private PopupHost popupHost1 = new PopupHost();

    public Page()
    {
        InitializeComponent();
    }

    private void OpenButton_Click(object sender, RoutedEventArgs e)
    {
        this.PageContent.Children.Add(popupHost1);
    }

    private void CloseButton_Click(object sender, RoutedEventArgs e)
    {
        this.PageContent.Children.Remove(popupHost1);
    }
}

答案 1 :(得分:2)

仅供参考,作为2009年3月发布的新Silverlight工具包的一部分,我们发布了一个Picker基类。 Picker类提供弹出功能,无需手动定位和显示弹出窗口。

如果您有兴趣,请给我一个大喊大叫,我会尽力在这里发布关于如何使用Picker的快速教程。 基本上是:

  1. 创建一个继承自Picker的类
  2. 在Blend中,编辑控件的模板
    1. 在模板中的弹出窗口中,在弹出窗口中放置您想要的内容(如按钮或其他内容)
    2. 在模板中的切换按钮旁边放置要显示弹出窗口关闭时的值的任何可视化。
  3. 为在2.1和2.2中创建的元素公开TemplateParts。
  4. OnApplyTemplate中的
  5. 使用GetTemplatePart
  6. 获取这些TemplatePart的实例
  7. 注册这些控件上的事件以响应其更改并更新控件。