2009-01-22 38 views
2

下面是设置:间歇InavlidCastException在UserControl.InitializeComponent()

我有一个Silverlight控件库“控件”,其中我具有用于呈现的对话框中定义的客户控制:

public class Dialog : ContentControl 
{ 
    public Dialog() 
     : base() 
    { 
     DefaultStyleKey = typeof(Dialog); 
    } 

<...normal custom control stuff...> 
} 

也默认样式在generic.xaml:

<Style TargetType="src_general:Dialog"> 
    <Setter Property="Padding" Value="25"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="src_general:Dialog"> 
       <Grid x:Name="RootElement" > 
        <vsm:VisualStateManager.VisualStateGroups> 
         <vsm:VisualStateGroup x:Name="DiakogStyleStates"> 
          <vsm:VisualState x:Name="OkCancel"> 
           <Storyboard> 
           </Storyboard> 
          </vsm:VisualState> 
          <vsm:VisualState x:Name="OkOnly"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Duration="0:0:0" Storyboard.TargetName="CancelButton" Storyboard.TargetProperty="Visibility" > 
             <DiscreteObjectKeyFrame KeyTime="0:0:0" > 
              <DiscreteObjectKeyFrame.Value> 
               <Visibility>Collapsed</Visibility> 
              </DiscreteObjectKeyFrame.Value> 
             </DiscreteObjectKeyFrame> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </vsm:VisualState> 
          <vsm:VisualState x:Name="CancelOnly"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Duration="0:0:0" Storyboard.TargetName="OkButton" Storyboard.TargetProperty="Visibility" > 
             <DiscreteObjectKeyFrame KeyTime="0:0:0" > 
              <DiscreteObjectKeyFrame.Value> 
                <Visibility>Collapsed</Visibility> 
              </DiscreteObjectKeyFrame.Value> 
             </DiscreteObjectKeyFrame> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </vsm:VisualState> 
          <vsm:VisualState x:Name="None"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Duration="0:0:0" Storyboard.TargetName="CancelButton" Storyboard.TargetProperty="Visibility" > 
             <DiscreteObjectKeyFrame KeyTime="0:0:0" > 
              <DiscreteObjectKeyFrame.Value> 
               <Visibility>Collapsed</Visibility> 
              </DiscreteObjectKeyFrame.Value> 
             </DiscreteObjectKeyFrame> 
            </ObjectAnimationUsingKeyFrames> 
             <ObjectAnimationUsingKeyFrames Duration="0:0:0" Storyboard.TargetName="OkButton" Storyboard.TargetProperty="Visibility" > 
             <DiscreteObjectKeyFrame KeyTime="0:0:0" > 
              <DiscreteObjectKeyFrame.Value> 
                <Visibility>Collapsed</Visibility> 
              </DiscreteObjectKeyFrame.Value> 
             </DiscreteObjectKeyFrame> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </vsm:VisualState> 
         </vsm:VisualStateGroup> 
        </vsm:VisualStateManager.VisualStateGroups> 
         <Popup x:Name="DialogPopup"> 
         <src_general:WindowFrame x:Name="Frame"> 
          <Grid > 
           <Grid.RowDefinitions> 
            <RowDefinition Height="*" /> 
            <RowDefinition Height="Auto" /> 
           </Grid.RowDefinitions> 

           <ContentPresenter Grid.Row="0" x:Name="ContentPresenter" Margin="{TemplateBinding Padding}"/> 
            <!--Action Buttons--> 
           <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="15"> 
            <src_general:GlassButton x:Name="CancelButton" Content="Cancel" Margin="2"/> 
            <src_general:GlassButton x:Name="OkButton" Content="Ok" Margin="2"/> 
           </StackPanel> 
          </Grid> 

         </src_general:WindowFrame> 
        </Popup> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

我在很多地方使用这个对话框没有问题。然而,在一个应用程序,从RootVisual嵌套约3-4用户控件,我用它的方式如下:

<general:Dialog x:Name="AddUpdateDialog" DialogStyle="OkCancel" Title="Add/Update Connection" Closed="AddUpdateDialog_Closed" ValidationGroup="AddConnection"> 
      <Grid Width="300"> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="Auto"/> 
        <ColumnDefinition Width="10"/> 
        <ColumnDefinition Width="*"/> 
       </Grid.ColumnDefinitions> 

       <TextBlock Grid.Row="0" Grid.Column="0" Text="Name:" Style="{StaticResource LabelText}"/> 
       <TextBox Grid.Row="0" Grid.Column="2" Text="{Binding Name, Mode=TwoWay}" Style="{StaticResource TextBoxInput}" MaxLength="49"> 
        <val:ValidationManager.Validator> 
         <val:RequiredValidator ManagerName="AddConnection" ErrorMessage="Name is required."/> 
        </val:ValidationManager.Validator> 
       </TextBox> 
      </Grid> 
     </general:Dialog> 

当我运行这个程序,我间歇性(约每5-10开始出现以下情况例外:

“无法投System.Windows.Controls.ContentControl类型的对象键入hookitupright.com.silverlight.controls.general.Dialog”。发生在InitializeComponent()用于上述XAML的父UserControl

具体而言,它在这里发生:

this.AddUpdateDialog = ((hookitupright.com.silverlight.controls.general.Dialog)(this.FindName("AddUpdateDialog"))); 

当我在那里放置一个断点时,大多数时候FindName都返回一个Dialog类型的对象,但有时它返回一个ContentControl(对话框的基础)并失败。 XAML没有改变。它是静态的...由于异常是间歇性的,发生在生成的代码中,所以我不知所措。

我曾尝试:

  1. 感动了所有的对话内容到一个单独的用户控件 - 似乎只是使问题变得更糟
  2. 注释掉的部分,看看它工作时......好,如果我完全注释掉TextBox,它不会再失败。其他一切(包括自定义验证附加属性)似乎都没有影响。

    2a。认为它可能与TwoWay绑定到TextBox有关,我删除了绑定。仍然失败。

更新:因此,考虑上述(2)我离开了文本框注释掉决定转移到其他的事情,回来这与希望,事情会自己透露给我。不幸的是,它似乎也失败了文本框,只是不太经常。

此外,我在同一个应用程序中的另一个用户控件中(和VisualTree中的同一级别)具有完全相同的配置,并且它完全不会失败。所以我从字面上复制并将失败的XAML粘贴到Main.xaml(我的根视觉)中,当然,它也不会在那里失败。假设XAML按顺序(从上到下)加载,失败的控件可能是最后一个加载的控件。我现在唯一的假设是,有一些计时事件正在发生,即Iam仍然加载可视化树,我开始通过WCF服务加载数据来获得完成的事件,并且这些事件在可视化树之前触发布局满载导致一些不良副作用...我会测试这个。

问题是,它不会每次都失败。它大约有20%的时间爆炸。当它工作时,甚至这个对话框都可以工作

如果不是相同的问题,这个问题是相关的:当我通过注释掉需要的功能来“修复”无效播放时,我会不太频繁但是间歇性地得到this无效属性(当属性/属性实际上存在时)。

+0

什么是最令人费解的是,我无法找出将使FindName在生成的代码返回的的对象基本类型ContentControl间歇性地。 – caryden 2009-01-22 21:49:00

回答

1

很多,很多的研究和挫折之后,我相信这是与此有关:http://blogs.msdn.com/silverlight_sdk/archive/2008/10/24/loaded-event-timing-in-silverlight.aspx

Silverlight中加载的事件不匹配的定义(一)什么是WPF,因此(B)他们从WPF粘贴到Silverlight文档中的定义

WTF ???

我修改了一些基于上述的代码,现在它似乎没有失败。我希望我能告诉你为什么它做了什么,为什么我修正了它(或者至少掩盖了它?),但我不能。也许别人会遇到这个问题,并可以弄清楚。

下面是我在做什么,我改变了:

文本框上方利用一个附加属性的一个验证器(如ASP.NET验证器和类似于Silverlight工具包的那些)。当一个Validator(RequireValidator的基类)被附加到一个控件时,它会链接到该控件以提供验证作为附加行为。诀窍是它然后尝试验证()当前控件。对于TextBox控件上的RequiredValidator,它为linkControl上的Text属性调用string.IsNullOrEmpty()。所有这些工作正常,因为这些只是TextBox控件的属性。但是,在此之后,验证程序需要以某种方式告诉控件显示错误指示符和任何错误消息。我通过提供包含两个新VisualStates(“ValidInput”&“InvalidInput”)的自定义样式来实现此目的,其中一个Style的元素是一个支持和接口的控件,称为IValidationNotificationControl。

好的,足够的背景。从文档中,我知道我只能访问TextBox样式的元素(新的visualStates和通知图标),因为我已经应用了模板,所以我迷上了验证器的linkelement的Loaded事件,并调用Validate()那是第一次。那么,MS的某人通过复制粘贴来自WPF的Loaded Event描述节省了大约15分钟的时间,并且花了我大约3-4天的心痛。事实证明,并不能保证该模板在silverlight中的Loaded Event中被应用。所以,我只是在Lokend事件处理函数中添加了一个对ApplyTemplate()的调用,失败消失了。

我的猜测是错误是间歇性的,因为布局(以及模板的应用)是异步发生的,有时在我点击加载事件时有时会出现,有时不是。但我仍然认为这是一个Silverlight错误,它表明错误在哪里出现,甚至可能指向一个安全漏洞(如果,但某些操作在代码中的其他位置,我可以使XAML解析器返回一个不同于实际的XAMl表示什么......)。哦,好吧......现在似乎在工作。也许这会帮助别人。

0

也许这可以帮助别人太:在另一个线程来看看我的answer