首页 > 解决方案 > 如何在 WPF/XAML MVVM 中将 ComboBoxes 的更改返回到 ObservableCollection

问题描述

我的 ViewModel 中有一个 ObservableCollection 汽车。汽车有两个属性,“Make”是一个字符串,而 Color 是一个自定义枚举。我已成功地将我的 Cars 集合绑定到 DataGrid,并且在 DataGrid 内,我有一个 Make 列和一个使用 ComboBox 的 Color 列。选定的值反映了我最初将 Car 设置为的值。用户可以从 ComboBox 中选择另一种颜色,但该选择不会更新回 ObservableCollection 中的 Car。我该怎么做呢?

我已将我的代码和 XAML 放在下面。任何帮助/指针都非常感谢!-戴夫

MainWindow(这是这个简单的演示,包括代码类和 ViewModel 类和汽车类):

using Library.EnumDefinitions;
using System;
using System.Collections.ObjectModel;
using System.Windows;

namespace TrickyBindingProblems
{

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowVM();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            foreach (ICar car in (DataContext as MainWindowVM).Cars)
            {
                Console.WriteLine(car.Color.ToString()); // NO CHANGES in Colors unfortunately!
            }
        }
    }

    public class MainWindowVM
    {
        public MainWindowVM()
        {
            Cars = new ObservableCollection<ICar>();
            Cars.Add(new Car(MyColor.Green, "Honda"));
            Cars.Add(new Car(MyColor.Blue, "GM"));
            Cars.Add(new Car());
        }
        public ObservableCollection<ICar> Cars { get; set; }

    }

    public class Car : ICar
    {
        public Car()
        {
            Color = MyColor.Red;
            Make = "Ford";
        }
        public Car(MyColor color, string make)
        {
            Color = color;
            Make = make;
        }
        public MyColor Color { get; set; }
        public string Make { get; set; }
    }

    public interface ICar
    {
        MyColor Color { get; set; }
        string Make { get; set; }
    }

}

我的枚举类(我把它放在一个不同的项目和命名空间中以反映一个更大的项目)

namespace Library.EnumDefinitions
{
    public enum MyColor
    {
        Red,
        Blue,
        Green
    }
}

最后是 XAML

<Window x:Class="TrickyBindingProblems.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TrickyBindingProblems"
        xmlns:enu="clr-namespace:Library.EnumDefinitions"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ObjectDataProvider x:Key="EnumDataProvider" MethodName="GetValues"
                        ObjectType="{x:Type sys:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="enu:MyColor" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <DataGrid Grid.Row="0" Grid.Column="1" 

                      Margin="0"
                      HorizontalAlignment="Left"
                      AutoGenerateColumns="False"
                      Background="Transparent"
                      DataContext="{Binding}"
                      HeadersVisibility="Column"
                      ItemsSource="{Binding Cars}"
                      SelectedItem="{Binding SelectedItemProperty, Mode=TwoWay}"
                      RowBackground="Transparent"
                      RowHeight="30">
            <DataGrid.CellStyle>
                <Style TargetType="{x:Type DataGridCell}">
                    <Setter Property="Foreground" Value="Black" />
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" Value="{x:Null}" />
                            <Setter Property="BorderBrush" Value="{x:Null}" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.CellStyle>
            <DataGrid.ColumnHeaderStyle>
                <Style TargetType="{x:Type DataGridColumnHeader}">
                    <Setter Property="FontWeight" Value="Bold" />
                </Style>
            </DataGrid.ColumnHeaderStyle>
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="*" Header="Make">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock VerticalAlignment="Center"
                                           Padding="5"
                                           Text="{Binding Make}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <DataGridTemplateColumn Width="*" Header="Color (as ComboBox)">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Source={StaticResource EnumDataProvider}}" SelectedItem="{Binding Color, Mode=TwoWay}">
                                <ComboBox.Resources>
                                    <Style TargetType="{x:Type TextBlock}">
                                        <Setter Property="Foreground" Value="Black" />
                                    </Style>
                                </ComboBox.Resources>
                            </ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <Button Grid.Row="2" Click="Button_Click">Push Me!</Button>
    </Grid>
</Window>

标签: wpfxamldata-bindingcomboboxobservablecollection

解决方案


推荐阅读