WPF, мультисвязывание CSV со списком флажков и лучшие практики MVVM - PullRequest
3 голосов
/ 04 ноября 2010

Я относительно новичок во всей идее WPF и MVVM, и я ищу советы по наилучшей практике. У меня есть решение, которое работает, но кажется, что мне не хватает какого-то замечательного синтаксиса XAML, который упростил бы все это.

У меня есть строковое поле в таблице базы данных, которая хранится в формате CSV, например "КОТОПЕС". Возможно, мне следовало бы сделать это как отношение многих ко многим в моей модели данных сущностей, но это другое обсуждение передовой практики.

В моем XAML я использую мультисвязывание с ListBox, который содержит CheckBoxes. Область возможных выборов определяется во время выполнения, и ListBox генерирует CheckBox с использованием 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 правильно проверяет правильные флажки, когда выбран объект, но при добавлении нового я выяснил, что мог бы использовать обработчики событий Checked и UnChecked CheckBox для обратной записи в мой объект, например так:

        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;
    }

Если вы все еще со мной, вопрос в том, как лучше это сделать? Я немного похож на яблоки и апельсины, когда использую конвертер для генерации представления из сущности, но затем использую обработчики событий для преобразования обновлений / команд представления обратно в сущность. Это нарушает какую-то цель MVVM использовать обработчики событий для изменения моей ViewModel таким образом?

Заранее спасибо за любые предложения, Ray

1 Ответ

1 голос
/ 17 февраля 2011

Рэй,

Если вы все еще со мной, вопрос в том, как лучше это сделать?

Я обнаружил, что с WPF, если вы задаете этот вопрос, то, вероятно, лучше .Есть так много опций (по сравнению с скудными WinForms).

Нарушает ли это какую-то цель MVVM использовать обработчики событий для изменения моей ViewModel таким образом?Да, это действительно нарушает MVVM.У вас не должно быть кода ViewModel (помимо настройки привязки ViewModel) в вашем коде позади.

Вы должны выполнять ваши события ICommand, которые предоставляются вашей ViewModel (т. Е. Add, Remove),См. EventToCommand , который, вероятно, будет применяться к вашим CheckBox_Checked и CheckBox_UnChecked событиям.

-jberger

...