为什么我的用户控件导致Visual Studio崩溃? [英] Why my user control crashes Visual Studio?

查看:162
本文介绍了为什么我的用户控件导致Visual Studio崩溃?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了一整天试图找出为什么这个用户控件崩溃VS2010(的Windows Phone 7.1开发)。应用程序运行没有问题这种控制,但是当我去MainPage.xaml中设计模式 - VS崩溃

 <用户控件X:类=blabla.Controls.Tile
的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/presentation
的xmlns:X =HTTP://模式.microsoft.com / WinFX的/ 2006 / XAML
的xmlns:D =http://schemas.microsoft.com/expression/blend/2008
的xmlns:MC =HTTP://模式.openxmlformats.org /标记兼容性/ 2006
MC:可忽略=D
的FontFamily ={StaticResource的PhoneFontFamilyNormal}
字号={StaticResource的PhoneFontSizeNormal}
前景={S​​taticResource的PhoneForegroundBrush}>

< UserControl.Resources>
<情节提要X:NAME =SwitchSidesAnimation>
< D​​oubleAnimationUsingKeyFrames Storyboard.TargetProperty =(UIElement.Projection)(PlaneProjection.RotationX)。Storyboard.TargetName =前端>
< EasingDoubleKeyFrame KeyTime =0值=0/>
< EasingDoubleKeyFrame KeyTime =0:0:0.2VALUE =90/>
< EasingDoubleKeyFrame KeyTime =0:0:0.4VALUE =90/>
< EasingDoubleKeyFrame X:NAME =MoveThisForPause1KeyTime =0:0:6VALUE = - 90/>
< EasingDoubleKeyFrame X:NAME =MoveThisForPause2KeyTime =0:0:6.2VALUE = - 90/>
< EasingDoubleKeyFrame X:NAME =MoveThisForPause3KeyTime =0:0:6.4VALUE =0/>
将; EasingDoubleKeyFrame X:名称=MoveThisForPause4KeyTime =0:0:12值=0/>
< / DoubleAnimationUsingKeyFrames>
< D​​oubleAnimationUsingKeyFrames Storyboard.TargetProperty =(UIElement.Projection)(PlaneProjection.RotationX)。Storyboard.TargetName =背面>
< EasingDoubleKeyFrame KeyTime =0值= - 90/>
< EasingDoubleKeyFrame KeyTime =0:0:0.2VALUE = - 90/>
将; EasingDoubleKeyFrame KeyTime =0:0:0.4值=0/>
将; EasingDoubleKeyFrame X:名称=MoveThisForPause5KeyTime =0:0:6值=0/>
< EasingDoubleKeyFrame X:NAME =MoveThisForPause6KeyTime =0:0:6.2VALUE =90/>
< EasingDoubleKeyFrame X:NAME =MoveThisForPause7KeyTime =0:0:6.4VALUE =90/>
< EasingDoubleKeyFrame X:NAME =MoveThisForPause8KeyTime =0:0:12VALUE =90/>
< / DoubleAnimationUsingKeyFrames>
< ObjectAnimationUsingKeyFrames Storyboard.TargetProperty =(UIElement.Visibility)Storyboard.TargetName =前端>
将; DiscreteObjectKeyFrame KeyTime =0:0:0.2>
< D​​iscreteObjectKeyFrame.Value>
<能见度和GT;可见的LT; /能见度和GT;
< /DiscreteObjectKeyFrame.Value>
< / DiscreteObjectKeyFrame>
将; DiscreteObjectKeyFrame KeyTime =0:0:0.4>
< D​​iscreteObjectKeyFrame.Value>
<能见度和GT;倒塌< /能见度和GT;
< /DiscreteObjectKeyFrame.Value>
< / DiscreteObjectKeyFrame>
将; DiscreteObjectKeyFrame X:名称=MoveThisForPause9KeyTime =0:0:6>
< D​​iscreteObjectKeyFrame.Value>
<能见度和GT;可见的LT; /能见度和GT;
< /DiscreteObjectKeyFrame.Value>
< / DiscreteObjectKeyFrame>
< D​​iscreteObjectKeyFrame X:NAME =MoveThisForPause10KeyTime =0:0:6.4>
< D​​iscreteObjectKeyFrame.Value>
<能见度和GT;可见的LT; /能见度和GT;
< /DiscreteObjectKeyFrame.Value>
< / DiscreteObjectKeyFrame>
将; DiscreteObjectKeyFrame X:名称=MoveThisForPause11KeyTime =0:0:12>
< D​​iscreteObjectKeyFrame.Value>
<能见度和GT;可见的LT; /能见度和GT;
< /DiscreteObjectKeyFrame.Value>
< / DiscreteObjectKeyFrame>
< / ObjectAnimationUsingKeyFrames>
< D​​oubleAnimationUsingKeyFrames Storyboard.TargetProperty =(UIElement.RenderTransform)(CompositeTransform.TranslateX)。Storyboard.TargetName =前端>
将; EasingDoubleKeyFrame KeyTime =0:0:0.4值=0/>
将; EasingDoubleKeyFrame X:名称=MoveThisForPause12KeyTime =0:0:6值=0/>
< EasingDoubleKeyFrame X:NAME =MoveThisForPause13KeyTime =0:0:6.2VALUE =0/>
< EasingDoubleKeyFrame X:NAME =MoveThisForPause14KeyTime =0:0:6.4VALUE =0/>
将; EasingDoubleKeyFrame X:名称=MoveThisForPause15KeyTime =0:0:12值=0/>
< / DoubleAnimationUsingKeyFrames>
< /故事板>
< /UserControl.Resources>

<电网X:NAME =LayoutRoot>
< Grid.ColumnDefinitions>
< ColumnDefinition WIDTH =1 */>
< /Grid.ColumnDefinitions>
< Grid.RowDefinitions>
< RowDefinition身高=1 */>
< /Grid.RowDefinitions>

<! - 正面 - >
将;网格X:名称=前侧Grid.Column =0Grid.Row =0
背景={结合FrontBackground}>
<图像来源={结合FrontImage}/>
< /网格和GT;
<! - /正面 - >

<! - 背面 - >
将;网格X:名称=背面Grid.Column =0Grid.Row =0
背景={结合BackBackground}>
< Grid.Projection>
< PlaneProjection =的rotationX - 90/>
< /Grid.Projection>
<图像来源={结合背景图像}/>
< /网格和GT;
<! - /反面 - >
< /网格和GT;
< /用户控件>

和现在的代码。

 命名空间blabla.Controls 
{
公共部分类瓷砖:用户控件
{
///<总结>
///定义是否瓷砖具有两面性。
///< /总结>
公共BOOL IsTwoSided
{
{返回(布尔)的GetValue(IsTwoSidedProperty); }

{
的SetValue(IsTwoSidedProperty,值);

this.startAnimations();
}
}

///<总结>
///图片,将上前方侧被显示。
///< /总结>
公众的BitmapImage FrontImage
{
{返回(的BitmapImage)的GetValue(FrontImageProperty); }
集合{的SetValue(FrontImageProperty,值); }
}

///<总结>
///形象地说生病要在背面显示。
///< /总结>
公共BitmapImage的背景图像
{
{返回(的BitmapImage)的GetValue(BackImageProperty); }
集合{的SetValue(BackImageProperty,值); }
}

///<总结>
///刷,将被用作背景前侧。
///< /总结>
公共刷FrontBackground
{
{返回(刷)的GetValue(FrontBackgroundProperty); }
集合{的SetValue(FrontBackgroundProperty,值); }
}

///<总结>
///刷,将被用作背景背面。
///< /总结>
公共刷BackBackground
{
{返回(刷)的GetValue(BackBackgroundProperty); }
集合{的SetValue(BackBackgroundProperty,值); }
}

//////////////////////////////////// ////////////////////////////////////////////////// /////////////////

公共静态只读的DependencyProperty IsTwoSidedProperty =
DependencyProperty.Register(IsTwoSided的typeof(布尔)的typeof(瓷砖),新PropertyMetadata(假));

公共静态只读的DependencyProperty FrontImageProperty =
DependencyProperty.Register(FrontImage的typeof(BitmapImage的)的typeof(瓦),新PropertyMetadata(NULL));

公共静态只读的DependencyProperty BackImageProperty =
DependencyProperty.Register(背景图像的typeof(BitmapImage的)的typeof(瓦),新PropertyMetadata(NULL));

公共静态只读的DependencyProperty FrontBackgroundProperty =
DependencyProperty.Register(FrontBackground的typeof(刷)的typeof(瓦),
新PropertyMetadata(新的SolidColorBrush((彩色)的应用.Current.Resources [PhoneAccentColor])));

公共静态只读的DependencyProperty BackBackgroundProperty =
DependencyProperty.Register(BackBackground的typeof(刷)的typeof(瓦),
新PropertyMetadata(新的SolidColorBrush((彩色)的应用.Current.Resources [PhoneAccentColor])));

////////////////////////////////////////// ////////////////////////////////////////////////// ///////////

公共瓷砖()
{
的InitializeComponent();
this.LayoutRoot.DataContext =这一点;
}

///////////////////////////////////// ////////////////////////////////////////////////// ////////////////

///<总结>
///:修改动画帧KeyTime调整时间的新时机。
///&下; PARAM NAME =pauseTime方式> Lenght暂停的&下; /参数>
///< /总结>
私人无效setPauses(时间跨度pauseTime)
{
//将暂停。
EasingDoubleKeyFrame frameToModify;

的for(int i = 0;真实的;我++)
{
如果(this.FindName(MoveThisForPause+我)!= NULL)
$ { b $ b frameToModify =(EasingDoubleKeyFrame)this.FindName(MoveThisForPause+ I);
frameToModify.KeyTime = KeyTime.FromTimeSpan(frameToModify.KeyTime.TimeSpan - TimeSpan.FromSeconds(5)+ pauseTime);
}
,否则
{
中断;
}
}
}

///<总结>
///启动动画。
///< /总结>
///< PARAM NAME =BEGINTIME>首先时间动画之前通常延迟< /参数>
私人无效startAnimations()
{
//我们开始动画只有瓷砖两面。
如果(this.IsTwoSided)
{
//停止以前的动画。
this.SwitchSidesAnimation.Stop();

//设置正确的暂停。
this.setPauses(TimeSpan.FromSeconds(新随机()接着(5,10))。);

//启动动画。
this.SwitchSidesAnimation.BeginTime = TimeSpan.FromSeconds(。新的随机()和Next(2,15));
this.SwitchSidesAnimation.RepeatBehavior = RepeatBehavior.Forever;
this.SwitchSidesAnimation.Begin();
}
,否则
{
this.SwitchSidesAnimation.Stop();
}
}
}
}


解决方案

我已经能够重现此崩溃,承认使用Silverlight的非手机版本,并在可视化Web开发快车,而不是VS的完整版本。



问题最终归结到这两个依赖属性声明中指定的默认​​值:

 公开静态只读的DependencyProperty FrontBackgroundProperty = 
DependencyProperty.Register(FrontBackground的typeof(刷)的typeof(瓦),
新PropertyMetadata(新的SolidColorBrush((彩色)Application.Current.Resources [PhoneAccentColor] )));

公共静态只读的DependencyProperty BackBackgroundProperty =
DependencyProperty.Register(BackBackground的typeof(刷)的typeof(瓦),
新PropertyMetadata(新的SolidColorBrush((彩色)的应用.Current.Resources [PhoneAccentColor])));



崩溃,走了之后,我换成(使用记事本++作为可视化Web开发Express时崩溃),删除项目的 OBJ 文件夹和重新启动的Visual Web开发快车。当我重新启动VWDX,它抱怨说,它找不到类型瓷砖,但那是因为我已经删除了 OBJ 文件夹。重建整理了这一点。



我只能猜测的问题是什么。在点瓷砖类被静态初始化, Application.Current 可能是 Application.Current.Resources 可能是应用.Current.Resources [PhoneAccentColor] 可能是(这将导致投地颜色失败,因为颜色结构)。也许VS设计师不处理得很好类型的静态初始化期间抛出的异常?



顺便说一句,我也想指出另一对夫妇的潜在问题。首先,这是你的 IsTwoSided 属性:

  ///<总结> 
///定义是否瓷砖具有两面性。
///< /总结>
公共BOOL IsTwoSided
{
{返回(布尔)的GetValue(IsTwoSidedProperty); }

{
的SetValue(IsTwoSidedProperty,值);

this.startAnimations();
}
}



看起来你想要的 startAnimations 来调用时,您的 IsTwoSided 依赖属性的改变方法。你上面写的代码将无法实现这一点。



在Silverlight的改变依赖属性的值,它不会打电话给你的财产setter方法​​来做到这一点。如果你想事情发生时,依赖属性的值发生变化,使用的属性更改回调来代替。



其次,在 Tile.xaml ,您声明故事板< UserControl.Resources> 如下:

 <情节提要X:NAME =SwitchSidesAnimation> 



我会建议使用 X:键代替的 X:名称,有两个原因:




  • 内的所有物品资源字典(除了隐含的方式)都必须有一个 X:键 X:名称来识别它们。 VS支持使用 X:名称 x的:关键,但存在作为的传统支持机制


  • 使用 X:名称在用户控制的XAML元素导致VS在创建该名称的字段的InitializeComponent()在你的瓷砖类(的自动生成的一部分 Tile.g.cs 内obj\Debug的地方)。然而,仅仅因为你能坚持 X:名称上的元素并不一定意味着你就可以访问所产生的场相应的对象。因为没有命名的UIElement SwitchSidesAnimation Tile.xaml (故事板是不是UI元素),在 SwitchSidesAnimation 字段将永远是



    事实上,的 MSDN文档为X:关键属性(也与上文)提到,




    一个FindName调用使用一个键值将不检索键控资源




    FindName 是使用的方法查找按名称的控件。如果你在 Tile.g.cs 看你会看到它使用那里。)




我总是推荐使用 X:键资源字典中这样你就不会导致相信你可以在代码中隐藏直接访问这个故事板。



要访问代码背后的故事板,用

  this.Resources [SwitchSidesAnimation]作为故事板

在事实上,如果你添加以下属性,你不会有改变你的 startAnimations 方法:

 私人故事板SwitchSidesAnimation 
{
{返回this.Resources [SwitchSidesAnimation]作为故事板; }
}


I've spent all day trying to figure out why this user control crashes VS2010 (Windows Phone 7.1 development). Application runs this control with no problem, but when I go to design mode in MainPage.xaml - VS crash.

<UserControl x:Class="blabla.Controls.Tile"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}">

    <UserControl.Resources>
        <Storyboard x:Name="SwitchSidesAnimation">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="FrontSide">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="90"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="90"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause1" KeyTime="0:0:6" Value="-90"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause2" KeyTime="0:0:6.2" Value="-90"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause3" KeyTime="0:0:6.4" Value="0"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause4" KeyTime="0:0:12" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="BackSide">
                <EasingDoubleKeyFrame KeyTime="0" Value="-90"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="-90"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause5" KeyTime="0:0:6" Value="0"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause6" KeyTime="0:0:6.2" Value="90"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause7" KeyTime="0:0:6.4" Value="90"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause8" KeyTime="0:0:12" Value="90"/>
            </DoubleAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="FrontSide">
                <DiscreteObjectKeyFrame KeyTime="0:0:0.2">
                    <DiscreteObjectKeyFrame.Value>
                        <Visibility>Visible</Visibility>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
                <DiscreteObjectKeyFrame KeyTime="0:0:0.4">
                    <DiscreteObjectKeyFrame.Value>
                        <Visibility>Collapsed</Visibility>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
                <DiscreteObjectKeyFrame x:Name="MoveThisForPause9" KeyTime="0:0:6">
                    <DiscreteObjectKeyFrame.Value>
                        <Visibility>Visible</Visibility>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
                <DiscreteObjectKeyFrame x:Name="MoveThisForPause10" KeyTime="0:0:6.4">
                    <DiscreteObjectKeyFrame.Value>
                        <Visibility>Visible</Visibility>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
                <DiscreteObjectKeyFrame x:Name="MoveThisForPause11" KeyTime="0:0:12">
                    <DiscreteObjectKeyFrame.Value>
                        <Visibility>Visible</Visibility>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
            </ObjectAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="FrontSide">
                <EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause12" KeyTime="0:0:6" Value="0"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause13" KeyTime="0:0:6.2" Value="0"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause14" KeyTime="0:0:6.4" Value="0"/>
                <EasingDoubleKeyFrame x:Name="MoveThisForPause15" KeyTime="0:0:12" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>

        <!-- Front side -->
        <Grid x:Name="FrontSide" Grid.Column="0" Grid.Row="0"
              Background="{Binding FrontBackground}">
            <Image Source="{Binding FrontImage}" />
        </Grid>
        <!-- /Front side -->

        <!-- Back side -->
        <Grid x:Name="BackSide" Grid.Column="0" Grid.Row="0"
              Background="{Binding BackBackground}">
            <Grid.Projection>
                <PlaneProjection RotationX="-90" />
            </Grid.Projection>
            <Image Source="{Binding BackImage}" />
        </Grid>
        <!-- /Back side -->
    </Grid>
</UserControl>

And now the code.

namespace blabla.Controls
{
    public partial class Tile : UserControl
    {
        /// <summary>
        /// Defines if the tile has two sides.
        /// </summary>
        public bool IsTwoSided
        {
            get { return (bool)GetValue(IsTwoSidedProperty); }
            set
            {
                SetValue(IsTwoSidedProperty, value);

                this.startAnimations();
            }
        }

        /// <summary>
        /// Image that will be displayed on front side.
        /// </summary>
        public BitmapImage FrontImage
        {
            get { return (BitmapImage)GetValue(FrontImageProperty); }
            set { SetValue(FrontImageProperty, value); }
        }

        /// <summary>
        /// Image that ill be displayed on back side.
        /// </summary>
        public BitmapImage BackImage
        {
            get { return (BitmapImage)GetValue(BackImageProperty); }
            set { SetValue(BackImageProperty, value); }
        }

        /// <summary>
        /// Brush that will be used as background for front side.
        /// </summary>
        public Brush FrontBackground
        {
            get { return (Brush)GetValue(FrontBackgroundProperty); }
            set { SetValue(FrontBackgroundProperty, value); }
        }

        /// <summary>
        /// Brush that will be used as background for back side.
        /// </summary>
        public Brush BackBackground
        {
            get { return (Brush)GetValue(BackBackgroundProperty); }
            set { SetValue(BackBackgroundProperty, value); }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////////

        public static readonly DependencyProperty IsTwoSidedProperty =
            DependencyProperty.Register("IsTwoSided", typeof(bool), typeof(Tile), new PropertyMetadata(false));

        public static readonly DependencyProperty FrontImageProperty =
            DependencyProperty.Register("FrontImage", typeof(BitmapImage), typeof(Tile), new PropertyMetadata(null));

        public static readonly DependencyProperty BackImageProperty =
            DependencyProperty.Register("BackImage", typeof(BitmapImage), typeof(Tile), new PropertyMetadata(null));

        public static readonly DependencyProperty FrontBackgroundProperty =
            DependencyProperty.Register("FrontBackground", typeof(Brush), typeof(Tile),
            new PropertyMetadata(new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"])));

        public static readonly DependencyProperty BackBackgroundProperty =
            DependencyProperty.Register("BackBackground", typeof(Brush), typeof(Tile),
            new PropertyMetadata(new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"])));

        ///////////////////////////////////////////////////////////////////////////////////////////////////////

        public Tile()
        {
            InitializeComponent();
            this.LayoutRoot.DataContext = this;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Modifies animation frames' KeyTime to adjust time for new timing.
        /// <param name="pauseTime">Lenght of the pause.</param>
        /// </summary>
        private void setPauses(TimeSpan pauseTime)
        {
            // Sets pauses.
            EasingDoubleKeyFrame frameToModify;

            for(int i = 0; true; i++)
            {
                if(this.FindName("MoveThisForPause" + i) != null)
                {
                    frameToModify = (EasingDoubleKeyFrame)this.FindName("MoveThisForPause" + i);
                    frameToModify.KeyTime = KeyTime.FromTimeSpan(frameToModify.KeyTime.TimeSpan - TimeSpan.FromSeconds(5) + pauseTime);
                }
                else
                {
                    break;
                }
            }
        }

        /// <summary>
        /// Starts animations.
        /// </summary>
        /// <param name="beginTime">Usually delay before first-time animation.</param>
        private void startAnimations()
        {
            // We start animations only if the tile is two sided.
            if(this.IsTwoSided)
            {
                // Stopping previous animation.
                this.SwitchSidesAnimation.Stop();

                // Sets correct pauses.
                this.setPauses(TimeSpan.FromSeconds(new Random().Next(5, 10)));

                // Starts animation.
                this.SwitchSidesAnimation.BeginTime = TimeSpan.FromSeconds(new Random().Next(2, 15));
                this.SwitchSidesAnimation.RepeatBehavior = RepeatBehavior.Forever;
                this.SwitchSidesAnimation.Begin();
            }
            else
            {
                this.SwitchSidesAnimation.Stop();
            }
        }
    }
}

解决方案

I have been able to reproduce this crash, admittedly using the non-Phone version of Silverlight, and in Visual Web Dev Express as opposed to the full version of VS.

The problem ultimately comes down to the default values specified in these two dependency property declarations:

    public static readonly DependencyProperty FrontBackgroundProperty =
        DependencyProperty.Register("FrontBackground", typeof(Brush), typeof(Tile),
        new PropertyMetadata(new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"])));

    public static readonly DependencyProperty BackBackgroundProperty =
        DependencyProperty.Register("BackBackground", typeof(Brush), typeof(Tile),
        new PropertyMetadata(new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"])));

The crash went away after I replaced the default values with null (using Notepad++ as Visual Web Dev Express was crashing), deleted the project's bin and obj folders and restarted Visual Web Dev Express. When I restarted VWDX, it complained that it couldn't find the type Tile, but that was because I had deleted the bin and obj folders. A rebuild sorted that out.

I can only guess at exactly what the problem is. At the point the Tile class is being statically initialized, Application.Current might be null, Application.Current.Resources might be null, or Application.Current.Resources["PhoneAccentColor"] might be null (which would cause the cast to Color to fail, as Color is a struct). Perhaps the VS designer doesn't handle very well exceptions thrown during static initialization of types?

Incidentally, I'd also like to point out another couple of potential problems. Firstly, this is your IsTwoSided property:

    /// <summary>
    /// Defines if the tile has two sides.
    /// </summary>
    public bool IsTwoSided
    {
        get { return (bool)GetValue(IsTwoSidedProperty); }
        set
        {
            SetValue(IsTwoSidedProperty, value);

            this.startAnimations();
        }
    }

It looks like you want the startAnimations method to be called whenever your IsTwoSided dependency property changes. The code you've written above will not achieve that.

When Silverlight changes the value of a dependency property, it doesn't call your the property setter to do this. If you want things to happen when a dependency property's value changes, use a property-changed callback instead.

Secondly, in Tile.xaml, you declare the Storyboard in <UserControl.Resources> as follows:

    <Storyboard x:Name="SwitchSidesAnimation">

I would recommend using x:Key instead of x:Name, for two reasons:

  • all items within resource dictionaries (except implicit styles) must have an x:Key or an x:Name to identify them. VS supports using x:Name in place of x:Key, but that exists as a legacy support mechanism only.

  • using x:Name in an element in a user-control XAML causes VS to create a field with that name in InitializeComponent() in the auto-generated part of your Tile class (in Tile.g.cs somewhere within obj\Debug). However, just because you can stick x:Name on an element doesn't necessarily mean you'll be able to access the corresponding object in the generated field. Because there is no UIElement named SwitchSidesAnimation in your Tile.xaml (Storyboards are not UIElements), the SwitchSidesAnimation field will always be null.

    Indeed, the MSDN documentation for the x:Key attribute (also linked to above) mentions that

    A FindName call using a key value will not retrieve a keyed resource

    (FindName is the method used to look up a control by name. If you look in Tile.g.cs you'll see it used there.)

I'd recommend always using x:Key within resource dictionaries so you're not led to believe that you can access this Storyboard directly in code-behind.

To access the storyboard in code-behind, use

    this.Resources["SwitchSidesAnimation"] as Storyboard

In fact, if you add the following property, you won't have to change your startAnimations method:

    private Storyboard SwitchSidesAnimation
    {
        get { return this.Resources["SwitchSidesAnimation"] as Storyboard; }
    }

这篇关于为什么我的用户控件导致Visual Studio崩溃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆