2009-01-22 30 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