为什么更改DataGrid ComboBox值根本不更新绑定属性?

时间:2016-09-18 18:20:00

标签: c# wpf mvvm combobox datagrid

我有DataGridComboBoxColumn应该显示整数或文本"默认"。当我添加行时,组合框从viewmodel的绑定属性中获取正确的值,但是当我在用户界面中更改值时,不会调用属性的集合。我尝试了SelectedValueBinding和SelectedItemBinding。从不调用转换器的ConvertBack。我不知道该事件应该被召唤。

有效的方法:

  • DataGrid SelectedItem binding
  • 双向绑定文本列(此处为了简洁而省略)

这是我的代码:

XAML:

<DataGrid Name="SelectionSetsGrid" CanUserAddRows="False" CanUserResizeColumns="True" CanUserSortColumns="True" 
                      ItemsSource="{Binding SelectionSets}" AutoGenerateColumns="False"
                      SelectedItem="{Binding SelectedSelectionSet}">
 <DataGrid.Columns>
  <DataGridComboBoxColumn Header="Width" SelectedValueBinding="{Binding LineWidthIndex}">
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox" BasedOn="{StaticResource Theme.ComboBox.Style}">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.LineWidths}"/>
            <Setter Property="IsReadOnly" Value="True"/>
            <Setter Property="ItemTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <WrapPanel>
                            <TextBlock Text="{Binding Converter={StaticResource IntToIntTextOrDefaultConverter}}" VerticalAlignment="Center"/>
                        </WrapPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox" BasedOn="{StaticResource Theme.ComboBox.Style}">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.LineWidths}"/>
            <Setter Property="ItemTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <WrapPanel>
                            <TextBlock Text="{Binding Converter={StaticResource IntToIntTextOrDefaultConverter}}" VerticalAlignment="Center"/>
                        </WrapPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
  </DataGridComboBoxColumn>
 </DataGrid.Columns>
</DataGrid>

ViewModel(ViewModel实现INotifyPropertyChanged和SetValue引发PropertyChanged):

public class SelectedObjectsViewModel : ViewModel
{
    private int[] _lineWidths = { -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    public ObservableCollection<int> LineWidths { get; private set; };

    private ObservableCollection<SelectionSetViewModel> _selectionSets;
    public ObservableCollection<SelectionSetViewModel> SelectionSets
    {
        get { return _selectionSets; }
        set { this.SetValue(ref _selectionSets, value); }
    }

    private SelectionSetViewModel _selectedSelectionSet;
    public SelectionSetViewModel SelectedSelectionSet
    {
        get { return this._selectedSelectionSet; }
        set { this.SetValue(ref _selectedSelectionSet, value); }
    }
}

DataGrid行的ViewModel(ViewModel实现INotifyPropertyChanged和SetValue引发PropertyChanged):

public class SelectionSetViewModel : ViewModel
{
    public SelectionSetViewModel()
    {
        LineWidthIndex = -1;
    }
    private int _lineWidthIndex;
    public int LineWidthIndex
    {
        get { return _lineWidthIndex; }
        set { SetValue(ref _lineWidthIndex, value); }
    }

转换器:

public class IntToIntTextOrDefaultConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        if ((int)value == -1)
            return Fusion.App.Current.Resources["StrDefault"].ToString();

        return value.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        return value.Equals(true) ? parameter : Binding.DoNothing;
    }
}

1 个答案:

答案 0 :(得分:1)

似乎在某些情况下,例如在编辑文本列并按Enter或添加新行后,属性WAS在更改组合框值后实际更新(设置为调用)。所以我刚刚将UpdateSourceTrigger = PropertyChanged添加到绑定中,并且对源属性的更新立即发生(而不是在一些随机操作之后)。请注意,从ComboBox更改焦点不足以更新源属性,因此我认为它从未更新过。

<DataGrid Name="SelectionSetsGrid" CanUserAddRows="False" CanUserResizeColumns="True" CanUserSortColumns="True" 
              ItemsSource="{Binding SelectionSets}" AutoGenerateColumns="False"
              SelectedItem="{Binding SelectedSelectionSet}">
        <DataGridComboBoxColumn Header="{StaticResource XpStrTopologyWidth}" SelectedItemBinding="{Binding LineWidthIndex, UpdateSourceTrigger=PropertyChanged}">
            <DataGridComboBoxColumn.ElementStyle>
                <Style TargetType="ComboBox" BasedOn="{StaticResource Theme.ComboBox.Style}">
                    <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.LineWidths}"/>
                    <Setter Property="IsReadOnly" Value="True"/>
                    <Setter Property="ItemTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <WrapPanel>
                                    <TextBlock Text="{Binding Converter={StaticResource IntToIntTextOrDefaultConverter}}" VerticalAlignment="Center"/>
                                </WrapPanel>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGridComboBoxColumn.ElementStyle>
            <DataGridComboBoxColumn.EditingElementStyle>
                <Style TargetType="ComboBox" BasedOn="{StaticResource Theme.ComboBox.Style}">
                    <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.LineWidths}"/>
                    <Setter Property="ItemTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <WrapPanel>
                                    <TextBlock Text="{Binding Converter={StaticResource IntToIntTextOrDefaultConverter}}" VerticalAlignment="Center"/>
                                </WrapPanel>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGridComboBoxColumn.EditingElementStyle>
        </DataGridComboBoxColumn>                        
    </DataGrid.Columns>
</DataGrid>