2

次のxamlがあるとしましょう...

<UserControl.Resources>
    <local:ViewModel x:Name="viewModel" />
    <local:LoadChildrenValueConverter x:Name="valueConverter" />
</UserControl.Resources>

<UserControl.DataContext>
    <Binding Source="{StaticResource viewModel}" />
</UserControl.DataContext>

<Grid x:Name="LayoutRoot" Background="White">
    <control:TreeView ItemsSource="{Binding Root}">
        <control:TreeView.ItemTemplate>
            <control:HierarchicalDataTemplate ItemsSource="{Binding Converter={StaticResource valueConverter}}">
                <TextBlock Text="{Binding}" />
            </control:HierarchicalDataTemplate>
        </control:TreeView.ItemTemplate>
    </control:TreeView>
</Grid>

...そしてそれに付随する次のコード...

システムを使用する;
System.Collections.ObjectModel の使用;
System.Windows.Data を使用します。

名前空間 SilverlightViewModelSpike
{
    パブリック クラス ViewModel
    {
        public ViewModel()
        {
            Root = new ObservableCollection() { "アイテム 1", "アイテム 2", "アイテム 3", };
        }

        public ObservableCollection ルート { get; プライベートセット; }        
    }

    public class LoadChildrenValueConverter : IValueConverter
    {
        public object Convert(オブジェクト値、タイプ targetType、オブジェクト パラメータ、System.Globalization.CultureInfo カルチャ)
        {
            return new ObservableCollection() { "アイテム 1", "アイテム 2", "アイテム 3", };
        }

        public object ConvertBack (オブジェクト値、Type targetType、オブジェクト パラメータ、System.Globalization.CultureInfo カルチャ)
        {
            新しい NotImplementedException() をスローします。
        }
    }
}

これは期待どおりに機能しますが、ビューに必要なデータを取得するために必要な 2 つの別個のクラスがあるのは違和感があります (ViewModel と LoadChildrenValueConverter が、ハード コーディングされたデータを返すのではなく、Web サービスからデータを取得したと想像してください)。ここでより良い解決策はありますか?こんなこともあるのかな…と思っていました。

システムを使用する;
System.Collections.ObjectModel の使用;
System.Windows.Data を使用します。

名前空間 SilverlightViewModelSpike
{
    パブリック クラス ViewModel
    {
        public ViewModel()
        {
            Root = new ObservableCollection() { "アイテム 1", "アイテム 2", "アイテム 3", };
            ValueConverter = new LoadChildrenValueConverter();
        }

        public ObservableCollection ルート { get; プライベートセット; }
        public LoadChildrenValueConverter ValueConverter { get; プライベートセット; }
    }

    public class LoadChildrenValueConverter : IValueConverter
    {
        public object Convert(オブジェクト値、タイプ targetType、オブジェクト パラメータ、System.Globalization.CultureInfo カルチャ)
        {
            return new ObservableCollection() { "アイテム 1", "アイテム 2", "アイテム 3", };
        }

        public object ConvertBack (オブジェクト値、Type targetType、オブジェクト パラメータ、System.Globalization.CultureInfo カルチャ)
        {
            新しい NotImplementedException() をスローします。
        }
    }
}

...しかし、この行を機能させることができません...

<control:HierarchicalDataTemplate ItemsSource="{???}">

...そして、それでも素晴らしい解決策とは思えません。誰もこれのためのすてきなきれいな解決策を持っていますか?

4

2 に答える 2

4

実際のモデルとビューの間に ViewModel を使用しているため、そこに IValueConverter ロジックを直接実装するだけの方が簡単ではないかと思います。のような並べ替え:

public class ViewModel
{
    public ObservableCollection Root { get; set: }

    public ObservableCollection Children
    {
        get { /* return children items */ }
    }
}

次に、2 番目のプロパティに直接バインドするだけです。

<control:HierarchicalDataTemplate ItemsSource="{Binding Children}">

ViewModel オブジェクトの主な目的は、元のモデルから必要なデータを取得するためにプルする必要がある "トリック" (IValueConverters など) の数を制限することだと思います。持っているので、それを利用することもできます。

編集 1

...そしてもちろん、あなたの投稿を読み直した今、それ以上のものがあることがわかりました。「ルート」コレクション内の各アイテムの子を取得しています。

ViewModel 自体に IValueConverter を静的インスタンスとして実装するのはどうですか?

public class ViewModel : IValueConverter
{ 
    public static readonly IValueConverter ChildrenConverter
        = new LoadChildrenValueConverter();
}

これで、次のように言えるはずです。

<control:HierarchicalDataTemplate 
    ItemsSource="{Binding Converter={x:Static local:ViewModel.ChildrenConverter}}">

編集 2

わかりました。Silverlight を使用しているため、{x:Static} は使用できません。

私が考えることができる唯一の他のオプションは、2 つを宣言する代わりに 1 つの静的リソースを再利用できるようにすることです。それは、ViewModel に IValueConverter を直接実装することです。これは、複数の種類の変換を行う必要がある場合には適していませんが、ViewModel の対象が非常に限定されている場合は、それでうまくいく可能性があります。そう:

public class ViewModel : IValueConverter
{
    // move your Convert and ConvertBack methods into here
}

今、あなたはこれを行うことができます:

<control:HierarchicalDataTemplate
    ItemsSource="{Binding Converter={StaticResource ViewModel}}">
于 2008-12-16T04:45:12.343 に答える
0

申し訳ありませんが、ここで何をしようとしているのか少し混乱しています... とにかく、タイトルから、値コンバーターのプロパティを値コンバーターのプロパティにしたいように聞こえます。最初に、私が書いた記事を見て、それを行う方法を正確に説明しています: http://nick-howard.blogspot.com/2011/06/silverlight-4-value-converter.html

したがって、LoadChildrenValueConverter に ObvervableCollection 依存関係プロパティを作成します。引数のために、それを Children と呼びましょう。

次に、xaml で LoadChildrenValueConverter を次のように変更できます。

そうすれば、ビュー モデルから Web サービスを 1 回呼び出すだけで、ビュー モデル内のその ObvervableCollection を値コンバーターと共有できます。

それが役立つことを願っています。

于 2011-06-09T05:35:54.580 に答える