2010-12-10 15 views
2

システムの目標に反しているように見えるバグのような動作が見られるため、.net 3.5から.net 4へのステップアップが欠けていますか?WPFのstaticresource DataTemplatesの論理リソースへの参照が実行時に解決されない

いくつかの例を使用して、作業用に単純なMVVMライブラリを作成しようとしています。私はいくつかの追加学習のためにTwitterクライアントアプリケーション内でそれを消費しており、大きな障害となっています。

シナリオはこれです。私のルートViewModel(TwitterClientViewModel)オブジェクトには、表示するDialogViewModelオブジェクトのインスタンスが与えられます。 DialogViewModelがコレクションに追加され、bool HasDialogsがtrueに設定されています。 PropertyChangedイベントはコレクションに対して呼び出され、必要に応じてフラグが呼び出されます。この部分は素晴らしいものです。

TwitterClientViewModelのビューはTwitterClientTemplateと呼ばれ、VisibleはDialogViewTemplate(DialogViewModelのビュー)ホスティングのオーバーレイになります。 Hosting ContentControlのテンプレートは、DynamicResource拡張子を持つDialogViewTemplateを参照します。これは、デザイナーと実行時に大きく表示されます。

これは不思議なことです。 DialogViewTemplateの 'body'は、DialogViewModel.Content(typeオブジェクト)にバインドされたコンテンツコントロールを持つダイアログコンテンツをホストします。期待していたのは、TemplateSelectorを使用すると(私は素晴らしい宣言を書いたが、テスト目的のためにコメントアウトしていた)、テキストとインタラクティブ要素の両方を表示できるということでした。たとえば、Twitterアカウントを認証する際にユーザーから詳細を要求します。この場合、PIN番号。

この時点では、ダイアログ実装のための2つのネストされたコンテンツコントロールがあります。テストの目的で、DialogViewTemplate本体のcontentcontrolはstaticresource拡張を使用してEnterPINDialogTemplate(EnterPINDialogViewModelのビュー)を取得します。最初は分離されていましたが、EnterPINDialogTemplateとDialogViewTemplateは同じファイルにあります(前者は最初に定義されています)。

実行時に、staticresource拡張機能はメッセージとともにXamlParseExceptionをスローします。 '' System.Windows.Markup.StaticResourceHolder 'の値が例外を送出しました。'

と内部例外メッセージ。

'' EnterPINDialogTemplate 'という名前のリソースが見つかりません。リソース名で大文字と小文字が区別される '

dynamicresourceを使用すると、リソースが解決されないときに期待通りに、ContentControlにEnterPINDialogViewModelタイプのFullnameが表示されます。 FrameWorkElement.FindResource()を呼び出すときに私のカスタムTemplateSelectorに侵入すると、同様の例外が送出されます(TryFindResourceはnullを返します)。

私の最初の考えは、データテンプレートが構築されたときに論理ツリーが分割され、以前のプロジェクトからその領域の問題が記憶されていたことでした。私は辞書がDataTemplateの内部からavaliableリソースを作るためのResourceDictionaryのMergeDictionariesプロパティを使用してみましたが、設計者はその1ビットを好きではなかった、とエラーがここで説明されていますhttp://connect.microsoft.com/VisualStudio/feedback/details/498844/wpf-designer-throws-invalidcastexception

はそのアイデアをスクラッチ。私はアプリケーション、ウィンドウ、TwitterClientTemplateレベルで辞書をマージしようとしましたが、運がなかった。

以下はxamlファイルです。

ダイアログテンプレート。XAML

<ResourceDictionary 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:VM="clr-namespace:EpicTweet.ViewModel" 
xmlns:ET="clr-namespace:EpicTweet" 
xmlns:T="clr-namespace:EpicTweet.Tools" 
xmlns:MV="clr-namespace:MVVM;assembly=MVVM" 
xmlns:Loc="clr-namespace:EpicTweet.Localization" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> 
<DataTemplate DataType="VM:EnterPINDialogViewModel" x:Key="EnterPINDialogTemplate"> 
    <Grid d:DesignWidth="453.89" d:DesignHeight="78.92" Loc:ResXManagerProperty.ResourceManager="{x:Static ET:Language.ResourceManager}"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto"/> 
      <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <Label Content="{Loc:ResxExtension ResourceName=String_PIN, FallbackValue='&lt;PIN&gt;'}"/> 
     <TextBox Grid.Column="1"/> 
     <TextBlock Grid.Row="1" Grid.RowSpan="2"></TextBlock> 
    </Grid> 
</DataTemplate> 
<DataTemplate x:Key="DialogViewTemplate" DataType="MV:DialogViewModel"> 
    <Border BorderBrush="Black" BorderThickness="1"> 
     <Grid d:DesignWidth="277.419" d:DesignHeight="74.96" Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" Height="Auto" Width="Auto"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition/> 
       <RowDefinition Height="Auto"/> 
      </Grid.RowDefinitions> 
      <Border d:LayoutOverrides="Width, Height" BorderThickness="0,0,0,1" BorderBrush="Black"> 
       <Label Content="{Binding DisplayName, FallbackValue=Header}" VerticalAlignment="Center" HorizontalAlignment="Left"/>  
      </Border> 
      <ContentControl Content="{Binding Content, FallbackValue=Body}" ContentTemplate="{StaticResource EnterPINDialogTemplate}" HorizontalAlignment="Stretch" d:LayoutOverrides="Height" Grid.Row="1" Margin="5"> 
       <!--<ContentControl.ContentTemplateSelector> 
        <T:TypeTemplateSelector> 
         <T:TemplateTypeRelationship Type="{x:Type VM:EnterPINDialogViewModel}" ResourceKey="EnterPINDialogTemplate"/> 
        </T:TypeTemplateSelector> 
       </ContentControl.ContentTemplateSelector>--> 
      </ContentControl> 
       <ItemsControl Grid.Row="2" Margin="10" 
       ItemsSource="{Binding Commands, Mode=OneTime, FallbackValue={x:Static VM:TwitterClientViewModel.DEFAULT_DIALOG_COMMANDS}}"> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <Button 
         Content="{Binding DisplayName, FallbackValue=CommandName, Mode=OneWay}" 
         Command="{Binding}"/> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
       <ItemsControl.ItemsPanel> 
        <ItemsPanelTemplate> 
         <WrapPanel Orientation="Horizontal"/> 
        </ItemsPanelTemplate> 
       </ItemsControl.ItemsPanel> 
      </ItemsControl> 
     </Grid> 
    </Border> 
</DataTemplate> 

TwitterClientDataTemplate.xaml

<ResourceDictionary 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:VM="clr-namespace:EpicTweet.ViewModel" 
xmlns:ET="clr-namespace:EpicTweet" 
xmlns:MV="clr-namespace:MVVM;assembly=MVVM" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> 
<ResourceDictionary.MergedDictionaries> 
    <ResourceDictionary Source="DialogTemplates.xaml"/> 
</ResourceDictionary.MergedDictionaries> 
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> 
<DataTemplate x:Key="TwitterClientTemplate" DataType="MV:TwitterClientViewModel"> 
    <ScrollViewer d:DesignWidth="285.083" d:DesignHeight="119.96"> 
     <Grid> 
      <StackPanel d:LayoutOverrides="Width, Height"> 
       <StackPanel Orientation="Horizontal"> 
        <Button Command="{Binding AddAccountCommand.Command}" Content="{Binding AddAccountCommand.DisplayName, FallbackValue=&lt;Add Account&gt;}"/> 
       </StackPanel> 
       <ContentControl/> 
      </StackPanel> 
      <Border BorderThickness="1" Background="#80000000" Visibility="{Binding HasDialogs, Converter={StaticResource BooleanToVisibilityConverter}, FallbackValue=Collapsed, Mode=OneWay}"> 
       <Grid VerticalAlignment="Stretch" MinWidth="50" MaxWidth="200"> 
        <ContentControl Content="{Binding Dialogs[0], Mode=OneWay}" ContentTemplate="{DynamicResource DialogViewTemplate}" HorizontalAlignment="Center" VerticalAlignment="Center"/> 
       </Grid> 
      </Border> 
     </Grid> 
    </ScrollViewer> 
</DataTemplate> 

あなたが私の唯一の希望だ、私はstackoverflowのヘルプ!

編集:この問題については、今後さらに作業しましたか?両方のテンプレートが同じファイル内にある場合は、dynamicresourceとstaticresource拡張子の両方が問題なくリソースを解決します。それらが別々のファイルにある場合、どのように辞書をマージするかにかかわらず、リソースは解決されません。各拡張子はnullを返します。

明らかに、解決策は両方のリソースを同じ辞書にスローすることですが、私が懸念している限り、これはハックであり、論理リソース検索システムの動作を意図していません。私は今、幸せなバニーではありません。これはかなり文書化されていないようです...

答えて

7

これまでにprattがあった場合、それは私です。この問題を解決しようとしている金曜日の夜に4時間を過ごした後、私はひどいエラーの報告としか言いようがありません。

ここは流行です。

<DataTemplate x:Key="TwitterClientTemplate" DataType="MV:TwitterClientViewModel"> 

<DataTemplate x:Key="TwitterClientTemplate" DataType="{x:Type MV:TwitterClientViewModel}"> 

およびBamする必要があり、それが動作します。

しかし、私の大きな悩みは残っています。なぜ誤った構文がデザイナーで動作しますが、実行時には機能しませんか?私の推測は、ランタイムの最適化はあまり作成されていないxamlで辞書に移入するのを煩わしくしないからですが、それが間違っているという警告を得るのは良いことです。

関連する問題