2

.net3.5から.net4へのステップアップで、システムの目標に反しているように見えるバグのある動作が見られるため、何かを見逃したことがありますか。

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

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

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

これは物事が奇妙になるところです。DialogViewTemplateの「本体」は、DialogViewModel.Content(タイプオブジェクト)にバインドされた追加のコンテンツコントロールを備えたダイアログコンテンツをホストします。TemplateSelector(私は素晴らしい宣言型のものを書きましたが、テスト目的でコメントアウトしました)を使用して、テキスト要素とインタラクティブ要素の両方を表示できることを期待していました。たとえば、Twitterアカウントを認証するときにユーザーに詳細を要求します。この場合、PIN番号。

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

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

および内部例外メッセージ。

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

dynamicresourceを使用すると、nullが返され、コンテンツコントロールにEnterPINDialogViewModelタイプのフルネームが表示されます。これは、リソースが解決されていない場合に予想されます。FrameWorkElement.FindResource()を呼び出すときにカスタムTemplateSelectorに侵入すると、同様の例外がスローされます(TryFindResourceはnullを返します)。

私が最初に考えたのは、データテンプレートが構築されるときに論理ツリーが分割されることであり、以前のプロジェクトでその領域の問題を思い出しました。ResourceDictionaryのMergeDictionariesプロパティを使用して、DataTemplate内からリソースディクショナリを使用できるようにしようとしましたが、デザイナーはその1ビットが気に入らなかったため、エラーについては次のように説明します: http ://connect.microsoft.com/VisualStudio/feedback/details / 498844 /wpf-designer-throws-invalidcastexception

そのアイデアをスクラッチします。アプリケーション、ウィンドウ、TwitterClientTemplateレベルで辞書をマージしようとしましたが、うまくいきませんでした。

以下はxamlファイルです。

DialogTemplates.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を返します。

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

4

1 に答える 1

7

プラットがあったとしたら、それは私です。金曜日の夜にこれを解決しようとして4時間後、私はそれをクラックしました。私が不安定なエラー報告としか呼べないもののおかげではありません。

これが話題です。

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

する必要があります

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

そして、バム、それは動作します。

しかし、私の大きな不満は残っています。デザイナでは正しくない構文が機能するのに、実行時には機能しないのはなぜですか?私の推測では、ランタイム最適化は、作成が不十分なxamlを辞書に入力する必要はありませんが、間違っているという警告を受け取ると便利です。

于 2010-12-13T12:47:31.383 に答える