【问题标题】:Why changing DataGrid ComboBox value does not update the bound property at all?为什么更改 DataGrid ComboBox 值根本不会更新绑定属性?
【发布时间】:2016-09-18 18:20:00
【问题描述】:

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

有效的方法:

  • DataGrid SelectedItem 绑定
  • 文本列双向绑定(此处省略)

这是我的代码:

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;
    }
}

【问题讨论】:

  • 一个幸运的问题可能是,绑定需要 Mode=TwoWay?
  • 当然,但 web 中的示例都没有在 DataGridComboBoxColumn 绑定定义中具有 Mode=TwoWay 。我试图以两种不同的方式将其放入,但没有奏效。此外,文本列在没有 Mode=TwoWay 的情况下工作。如果您知道如何正确地将其放入 XAML 中,我会很高兴 :)
  • 因为我以前也使用过复选框绑定,所以这是我自己的代码的一部分:&lt;DataGridCheckBoxColumn Header="some header" Binding="{Binding headerBinding}" Width="80"&gt;。更改了名称,但希望这会有所帮助。

标签: c# wpf mvvm combobox datagrid


【解决方案1】:

似乎在某些情况下,例如在编辑文本列并按 Enter 键或添加新行之后,更改组合框值后属性实际上已更新(设置调用)。所以我只是将 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>

【讨论】:

    猜你喜欢
    • 2014-04-13
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多