Why my user control crashes Visual Studio?

后端 未结 2 1247
醉酒成梦
醉酒成梦 2020-12-21 17:59

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 t

相关标签:
2条回答
  • 2020-12-21 18:15

    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; }
        }
    
    0 讨论(0)
  • 2020-12-21 18:18

    I had similar problem (while developing Silverlight 5), which took me almost 3 days to struggle, and would take surely more, but luckily here I have found the solution (by Luke Woodward).

    In my case I was using:

        public static readonly DependencyProperty MyStyleProperty = 
            DependencyProperty.Register(
                "MyStyle",
                typeof(Style), 
                typeof(MainButton), 
                new PropertyMetadata(
                        // using this construct as a default value 
                        // makes VS 2010 SP1 to crush!
                        Application.Current.Resources["SomeStyle"] as Style, 
                        OnPropertyChanged
                )
            );
    

    So the common thing in both problems is using some resource value as a default value for DependencyProperty.

    But what is more tragic, this problem occured only after I applied SP1 for VS 2010 (since I wanted to develop in Silverlight 5, which required SP1 for VS 2010).

    This brought me headache and a lot of time to search.

    Fortunately now it is solved now, thanks!

    0 讨论(0)
提交回复
热议问题