我的WPF DataGrid中的ComboBox不会显示任何项目

时间:2011-12-01 19:06:35

标签: wpf mvvm datagrid

我有一个包含DataGrid的WPF用户控件。这个DG包含几个列,包括状态的ComboBox。填充状态列表并将其存储为我的ViewModel中的属性。

我正在尝试将StateList属性绑定到我的Combobox的ItemsSource,但是当我运行表单并尝试编辑DG时,组合框不包含任何值,组合框是空的。

这是用户控件的XAML。

<UserControl x:Class="myproject.View.ucContactView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" d:DesignHeight="475" d:DesignWidth="977">
<UserControl.Resources>
    <ResourceDictionary Source="/Templates/MyResourceDictionary.xaml"/>
</UserControl.Resources>
<Grid DataContext="{Binding ViewModel}">
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding AddressCollectionViewSource.View}">
        <DataGridTemplateColumn Header="State" Width="160">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding StateDescription}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <ComboBox Name="cboState"
                                  SelectedValuePath="StateKey"
                                  ItemTemplate="{StaticResource dtStateTemplate}"
                                  ItemsSource="{Binding StateList}" 
                                  SelectedItem="{Binding StateKey, Mode=TwoWay}"
                                  Width="100" />
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
    </DataGrid>
</Grid>
</UserControl>

奇怪的是,如果我使用完全相同的组合框在此用户控件上创建另一个组合框,则此组合框可按预期工作。

<!-- this works as long as it's not in the DG -->
<StackPanel Height="126" HorizontalAlignment="Left" Margin="766,275,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="200" >
    <ComboBox Name="cboState2"
          SelectedValuePath="StateKey"
          ItemTemplate="{StaticResource dtStateTemplate}"
          ItemsSource="{Binding StateList}" 
          SelectedItem="{Binding StateKey, Mode=TwoWay}"
          Width="100" />
</StackPanel>

为什么DG中的组合框不会显示StateList属性中的值?为什么单独的组合框能正常工作?

2 个答案:

答案 0 :(得分:2)

这不起作用,因为您的ComboBox正在寻找StateList作为DataContext的{​​{1}}的属性。也就是说,当它需要绑定到DataGrid时,它会尝试绑定到ViewModel.AddressCollectionViewSource.View.StateList。在调试时检查输出窗口,我打赌你会看到ViewModel.StateList的效果的绑定错误。

请改为尝试:

Could not find property StateList on object AddressCollectionViewSource (or maybe ICollection)

答案 1 :(得分:1)

如果您的viewmodel是窗口中的属性,则可以执行此操作

ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ViewModel.StateList, Mode=OneWay}"


<Window x:Class="WpfStackOverflowSpielWiese.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window2"
        Height="300"
        Width="300"
        x:Name="window">

  <Grid DataContext="{Binding ElementName=window, Path=ViewModel}">

    <DataGrid x:Name="grid"
              AutoGenerateColumns="False"
              ItemsSource="{Binding AddressCollectionViewSource, Mode=OneWay}">

      <DataGrid.Columns>
        <DataGridTemplateColumn Header="State"
                                Width="160">

          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding StateKey}" />
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>

          <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
              <StackPanel Orientation="Horizontal">
                <ComboBox Name="cboState"
                          SelectedValuePath="StateKey"
                          ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ViewModel.StateList, Mode=OneWay}"
                          SelectedItem="{Binding StateKey, Mode=TwoWay}"
                          Width="100" />
              </StackPanel>
            </DataTemplate>
          </DataGridTemplateColumn.CellEditingTemplate>

        </DataGridTemplateColumn>
      </DataGrid.Columns>

    </DataGrid>
  </Grid>
</Window>


using System.Collections.ObjectModel;
using System.Windows;

namespace WpfStackOverflowSpielWiese
{
  /// <summary>
  /// Interaction logic for Window2.xaml
  /// </summary>
  public partial class Window2 : Window
  {
    public static readonly DependencyProperty ViewModelProperty =
      DependencyProperty.Register("ViewModel", typeof(ViewModelClass), typeof(Window2), new PropertyMetadata(default(ViewModelClass)));

    public ViewModelClass ViewModel {
      get { return (ViewModelClass)this.GetValue(ViewModelProperty); }
      set { this.SetValue(ViewModelProperty, value); }
    }

    public Window2() {
      this.InitializeComponent();
      this.grid.Items.Clear();
      this.ViewModel = new ViewModelClass();
    }
  }

  public class StateClass : DependencyObject
  {
    public static readonly DependencyProperty StateKeyProperty =
      DependencyProperty.Register("StateKey", typeof(string), typeof(ViewModelClass), new PropertyMetadata(default(string)));

    public string StateKey {
      get { return (string)this.GetValue(StateKeyProperty); }
      set { this.SetValue(StateKeyProperty, value); }
    }

    public static readonly DependencyProperty StateProperty =
      DependencyProperty.Register("State", typeof(string), typeof(StateClass), new PropertyMetadata(default(string)));

    public string State {
      get { return (string)this.GetValue(StateProperty); }
      set { this.SetValue(StateProperty, value); }
    }
  }

  public class ViewModelClass : DependencyObject
  {
    public static readonly DependencyProperty StateListProperty =
      DependencyProperty.Register("StateList", typeof(ObservableCollection<string>), typeof(ViewModelClass), new PropertyMetadata(default(ObservableCollection<string>)));

    public static readonly DependencyProperty AddressCollectionViewSourceProperty =
      DependencyProperty.Register("AddressCollectionViewSource", typeof(ObservableCollection<StateClass>), typeof(ViewModelClass), new PropertyMetadata(default(ObservableCollection<StateClass>)));

    public ObservableCollection<StateClass> AddressCollectionViewSource {
      get { return (ObservableCollection<StateClass>)this.GetValue(AddressCollectionViewSourceProperty); }
      set { this.SetValue(AddressCollectionViewSourceProperty, value); }
    }

    public ObservableCollection<string> StateList {
      get { return (ObservableCollection<string>)this.GetValue(StateListProperty); }
      set { this.SetValue(StateListProperty, value); }
    }

    public ViewModelClass() {
      this.StateList = new ObservableCollection<string>(new[] {"one", "two"});
      this.AddressCollectionViewSource = new ObservableCollection<StateClass>(new[] {new StateClass {State = "state", StateKey = "one"}});
    }
  }
}