DataGridComboBoxColumn不显示ObservableCollection

时间:2014-11-22 23:30:22

标签: c# .net wpf xaml mvvm

示例代码:

class GameListViewModel {
    private IGameRepository repository;
    public GameViewModel GameViewModel { get; set; }
    public ObservableCollection<GameViewModel> Games { get; set; }
    public ObservableCollection<GenreViewModel> Genres { get; set; }
    public ICommand AddGame_ { get; set; }

    public GameListViewModel() {
        repository = new DummyGameRepository();
        GameViewModel = new GameViewModel();
        Games = new ObservableCollection<GameViewModel>(repository.GameList().Select(game => new GameViewModel(game)));
        Genres = new ObservableCollection<GenreViewModel>(repository.GameList().Select(game => game.Genre).Distinct().Select(genre => new GenreViewModel(genre)));
        AddGame_ = new RelayCommand(AddGame, CanAddGame);
    }
}

class Game {
    public string Title { get; set; }
    public string SubTitle { get; set; }
    public int Pegi { get; set; }
    public Genre Genre { get; set; }
}

XAML:

    <DataGrid ItemsSource="{Binding Games}" AutoGenerateColumns="False" Margin="0,32">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Title" Binding="{Binding Title}" />
            <DataGridTextColumn Header="Sub-Title" Binding="{Binding SubTitle}" />
            <DataGridTextColumn Header="Pegi" Binding="{Binding Pegi}" />
            <DataGridTextColumn Header="Genre" Binding="{Binding Genre.Name}" />

            <DataGridComboBoxColumn Header="Test" ItemsSource="{Binding Genres}" DisplayMemberPath="Name" />
        </DataGrid.Columns>
    </DataGrid>

问题是,我希望组合框能够动态地显示添加到游戏中的所有可能类型。为此,我在GameListViewModel中创建了一个ObservableCollection。这是行不通的!我现在已经苦苦挣扎了2个小时......后来我希望所选的值成为游戏中的类型。

1 个答案:

答案 0 :(得分:3)

啊,你发现了许多WPF开发人员的贪婪的来源 - DataGrid没有将它的DataContext转发给列。你不能真正依赖于像ColumnSource = {Binding Genres}这样的语句,因为框架无法解决它。这太烦人了。

此外,您还没有设置SelectedItemBinding - 这是一个工作示例:

XAML:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.Resources>
        <CollectionViewSource Source="{Binding Possibilities}" x:Key="possibilities"/>
    </Grid.Resources>

    <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False" x:Name="dataGrid">
        <DataGrid.Columns>
            <DataGridComboBoxColumn Header="test" 
                                    SelectedItemBinding="{Binding Selection}"
                                    ItemsSource="{Binding Source={StaticResource possibilities} }">

            </DataGridComboBoxColumn>

        </DataGrid.Columns>
    </DataGrid>
</Grid>
</Window>

cs代码隐藏:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ViewModel()
        {
            Items = new ObservableCollection<Item>()
            {
                new Item(){
                    Selection ="A"
                }
            }
        };
    }
}

public class Item : ViewModelBase
{
    private string _selection = null;

    public string Selection
    {
        get { return _selection; }
        set { _selection = value; OnPropertyChanged("Selection"); }
    }
}

public class ViewModel : ViewModelBase
{
    private ObservableCollection<Item> _items = new ObservableCollection<Item>();

    public ObservableCollection<Item> Items
    {
        get { return _items; }
        set { _items = value; OnPropertyChanged("Items"); }
    }

    private ObservableCollection<string> _possibilities = new ObservableCollection<string>()
    {
        "A", "B", "C"
    };

    public ObservableCollection<string> Possibilities
    {
        get
        {
            return _possibilities;
        }
        set
        {
            _possibilities = value;
            OnPropertyChanged("Possibilites");
        }
    }
}

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        var propChanged = PropertyChanged;
        if (propChanged != null)
            propChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

以下是一些有用的链接: 这个应该工作: http://blogs.msdn.com/b/jaimer/archive/2008/11/22/forwarding-the-datagrid-s-datacontext-to-its-columns.aspx

此处显示的最后一个解决方案特别相关: http://blogs.msdn.com/b/vinsibal/archive/2008/12/17/wpf-datagrid-dynamically-updating-datagridcomboboxcolumn.aspx