3

私はWPFとMVVMのアイデア全体に比較的慣れていないので、ベストプラクティスに関するアドバイスを探しています。動作するソリューションがありますが、全体を単純化する優れたXAML構文が欠落しているように感じます。

「CAT、DOG」などのCSVとして保存されているデータベーステーブルに文字列フィールドがあります。おそらく、エンティティデータモデルで多対多の関係としてこれを行うべきでしたが、それは別のベストプラクティスの議論です。

XAMLでは、CheckBoxを含むListBoxでマルチバインディングを使用しています。可能な選択肢のドメインは実行時に決定され、ListBoxはDataTemplateを使用してチェックボックスを生成します。XAMLは次のとおりです。

    <ListBox Grid.Column="3" Grid.Row="8" Grid.RowSpan="2" Name="brandedProductsListBox" Margin="3" ItemsSource="{Binding Source={StaticResource brandedProductLookup}}" IsSynchronizedWithCurrentItem="True" TabIndex="475">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Margin="3" Content="{Binding Path=BrandedProductName}" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked">
                <CheckBox.IsChecked>
                    <MultiBinding Converter="{StaticResource brandedProductToBoolean}">
                        <Binding Source="{StaticResource projectsView}" Path="BrandedProducts" />
                        <Binding Path="BrandedProductName" />
                    </MultiBinding>
                </CheckBox.IsChecked>
            </CheckBox>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ListBox>

コンバーターを使用して、適切なチェックボックスをチェックします。コンバーターのConvertBackメソッドを取得してブール値をCSV文字列に変換しようとしましたが、渡されたすべてのBrandedProductNameにアクセスする方法がわかりませんでした。コンバーターは次のとおりです。

public class BrandedProductToBooleanConverter : IMultiValueConverter
{
    public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null) {
            return false;
        }
        else {
            // The bindings passed in (in order) are: the BrandedProducts field for the current project, 
            // and the Branded Product represented by the current CheckBox.
            string brandedProducts = value[0] as string;
            string brandedProduct = value[1] as string;
            return brandedProducts == null ? false :  brandedProducts.Contains(brandedProduct);
        }
    }

    public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

したがって、Convertは、エンティティが選択されたときに適切なチェックボックスを適切にチェックしますが、新しいチェックボックスを追加するときに、CheckBoxのCheckedおよびUnCheckedイベントハンドラーを使用して、次のようにエンティティに書き戻すことができると考えました。

        private void CheckBox_Checked(object sender, RoutedEventArgs e)
    {
        if (projectView.IsAddingNew) {
            CheckBox checkBox = sender as CheckBox;
            NewProject project = projectView.CurrentAddItem as NewProject;
            if (project.BrandedProducts == null) {
                project.BrandedProducts = (string)checkBox.Content;
            }
            else {
                project.BrandedProducts += ", " + (string)checkBox.Content;
            }
        }
        e.Handled = true;
    }

    private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
    {
        if (projectView.IsAddingNew) {
            CheckBox checkBox = sender as CheckBox;
            NewProject project = projectView.CurrentAddItem as NewProject;
            if (project.BrandedProducts != null) {
                project.BrandedProducts = project.BrandedProducts.Replace((string)checkBox.Content + ", ", "").Replace(", " + (string)checkBox.Content, "");
            }
        }
        e.Handled = true;
    }

あなたがまだ私と一緒にいるなら、問題はこれを行うためのより良い方法は何ですか?コンバーターを使用してエンティティからビューを生成し、イベントハンドラーを使用してビューの更新/コマンドをエンティティに戻すと、リンゴとオレンジのように感じます。イベントハンドラーを使用してViewModelをこのように変更することは、MVVMのいくつかの目標に違反しますか?

提案を事前にありがとう、レイ

4

1 に答える 1

1

レイ、

あなたがまだ私と一緒にいるなら、問題はこれを行うためのより良い方法は何ですか?

WPFを使用すると、この質問をする場合は、おそらくより良い方法があることがわかりまし。(弱虫のWinFormsと比較して)非常に多くのオプションがあります。

イベントハンドラーを使用してViewModelをこのように変更することは、MVVMのいくつかの目標に違反しますか?

IMHO、はい、MVVMに違反しています。コードビハインドには、(ViewModelバインディングの設定以外に)ViewModelコードを含めないでください。

ViewModelによって公開されるイベントを実行する必要がありますICommand(つまり、追加、削除)。おそらくあなたとイベントに適用されるEventToCommandを参照してください。CheckBox_CheckedCheckBox_UnChecked

-jberger

于 2011-02-17T18:11:20.477 に答える