WPF,将CSV多重绑定到复选框的列表框,以及MVVM最佳实践

时间:2010-11-04 13:43:47

标签: wpf mvvm multibinding

我对整个WPF和MVVM的想法相对较新,我正在寻找最佳实践的建议。我有一个有效的解决方案,但感觉我可能会遗漏一些可以简化整个事情的优秀XAML语法。

我在数据库表中有一个字符串字段,存储为CSV格式,例如“猫狗”。也许我应该在我的实体数据模型中将其作为多对多关系来完成,但这是一个不同的最佳实践讨论。

在我的XAML中,我在包含CheckBoxes的ListBox上使用多绑定。可选选项的域在运行时确定,ListBox使用DataTemplate生成CheckBoxes。这是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>

我使用转换器检查相应的CheckBoxes。我试图让转换器的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;
    }
}

因此转换在选择实体时正确检查了正确的CheckBox,但是在添加新的时我发现我可以使用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;
    }

如果你还在我身边,问题是什么是更好的方法呢?感觉有点像苹果和橘子,我使用转换器从实体生成视图,然后使用事件处理程序将视图更新/命令转换回实体。是否违反MVVM的某些目标,使用事件处理程序以这种方式修改我的ViewModel?

提前感谢任何建议, 射线

1 个答案:

答案 0 :(得分:1)

  

如果你还在我身边,那么问题就在于此   这是一个更好的方法吗?

我发现使用WPF,如果你问这个问题,那么可能是更好的方法。有很多选择(与wimpy WinForms相比)。

  

是否违反了MVVM的某些目标   使用事件处理程序来修改我的   ViewModel这样吗?

恕我直言,是的,它确实违反了MVVM。在代码隐藏中你应该没有ViewModel代码(除了设置ViewModel绑定)。

您应该让您的事件执行由ViewModel公开的ICommand(即添加,删除)。请参阅可能适用于CheckBox_CheckedCheckBox_UnChecked事件的EventToCommand

-jberger