将WPF DataGridComboBoxColumn与MVVM结合使用 - 绑定到ViewModel中的属性

时间:2010-08-25 04:51:28

标签: wpf mvvm wpfdatagrid mvvm-light

我正在使用优秀的MVVM Light Toolkit。我的ViewModel公开了:

public const string CourtCodesTypeCourtPropertyName = "CourtCodesTypeCourt";
private List<CourtType> _courtCodesTypes = new List<CourtType>();
public List<CourtType> CourtCodesTypeCourt
{
    get
    {
        return _courtCodesTypes;
    }

    set
    {
        if (_courtCodesTypes == value)
        {
            return;
        }

        var oldValue = _courtCodesTypes;
        _courtCodesTypes = value;

        // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
        RaisePropertyChanged(CourtCodesTypeCourtPropertyName, oldValue, value, true);
    }
}

public const string CourtCodesPropertyName = "CourtCodes";
private List<Court> _courtCodes = null;
public List<Court> CourtCodes
{
    get
    {
        return _courtCodes;
    }

    set
    {
        if (_courtCodes == value)
        {
            return;
        }

        var oldValue = _courtCodes;
        _courtCodes = value;

        // Update bindings and broadcast change using GalaSoft.Utility.Messenging
        RaisePropertyChanged(CourtCodesPropertyName, oldValue, value, true);
    }
}

View有一个DataGrid:

<DataGrid
      ItemsSource="{Binding CourtCodes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
      AutoGenerateColumns="False"
      AlternatingRowBackground="{DynamicResource OffsetBrown}"
      AlternationCount="1" Margin="45,0">
   <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Abbreviation, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
         Header="Abbreviation"
         Width="25*" />
    <DataGridTextColumn Binding="{Binding FullName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
         Header="Court"
         Width="75*" />
    <DataGridComboBoxColumn Header="CourtType" 
         ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CourtCodesTypeCourt} TextBinding="{Binding CourtTypeDescription}""/>
   </DataGrid.Columns>
  </DataGrid>

如您所见,DataCrid有一个ItemsSource,来自CourtCodes。我希望CourtType列是CourtCodesTypeCourt中包含的所有枚举CourtType的下拉列表。对于我的生活,我似乎无法用任何东西填充DataGridComboBoxColumn。目前失败的尝试是想使用RelativeSource ......我做错了什么?

除了不工作之外,我看到的两个错误是:

  

System.Windows.Data错误:4:不能   找到与参考绑定的源   'RelativeSource FindAncestor,   AncestorType = 'System.Windows.Window',   AncestorLevel = '1'”。   BindingExpression:路径= DataContext.CourtCodesTypeCourt;   的DataItem = NULL;目标元素是   'DataGridComboBoxColumn'   (的HashCode = 38771709);目标财产   是'ItemsSource'(输入'IEnumerable')

  

System.Windows.Data错误:40:   BindingExpression路径错误:   'CourtCodesTypeCourt'属性不是   找到'对象'''法院'   (的HashCode = 38141773)”。   BindingExpression:路径= CourtCodesTypeCourt.CourtTypeDescription;   DataItem ='Court'(HashCode = 38141773);   目标元素是'ComboBox'   (名称= '');目标属性是'文字'   (输入'String')

3 个答案:

答案 0 :(得分:28)

DataGrid列定义不会以您期望的方式参与逻辑树。这很荒谬,但最后我检查过你必须做这样的事情:

<DataGridComboBoxColumn Header="CourtType" SelectedItemBinding="{Binding Type}">
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CourtCodesTypeCourt}"/>
            <Setter Property="IsReadOnly" Value="True"/>
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CourtCodesTypeCourt}"/>
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>

您会注意到我已将TextBinding更改为SelectedItemBinding。我不确定您是否真的打算使用TextBinding,但如果您只是想让用户在列表中进行选择,那么SelectedItemBinding可能就是您想要的。

此外,您的虚拟机并未完全遵循最佳做法。您使用的是List<T>而不是ObservableCollection<T>,并且您将其显示为List<T>,而不是ICollection<T>等更简单的内容。

答案 1 :(得分:3)

我在这里找到了答案http://cinch.codeplex.com/discussions/239522

对于DataGridComboBoxColumn,您必须创建ItemsSource的StaticRecource,如:

<CollectionViewSource Source="{Binding Element=theView, Path=DataContext.ViewModelCollection1}" x:Key="ViewModelCollection1" />

并使用以下命令将其绑定到DataGridComboBoxColumn:

ItemsSource="{Binding Source={StaticResource ViewModelCollection1}}"

这是因为DataGridColumns不是可视树的一部分。

如果要绑定DataGrid项的集合,则必须将ItemsSource设置为两种样式:

<DataGridComboBoxColumn.ElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding Path=ModelCollection1}" />
    </Style> </DataGridComboBoxColumn.ElementStyle> <DataGridComboBoxColumn.EditingElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding Path=ModelCollection1}" />
    </Style> </DataGridComboBoxColumn.EditingElementStyle>

答案 2 :(得分:-1)