WPF组合框不会更新当前选定的项目

时间:2017-08-31 23:42:54

标签: c# wpf combobox

我的组合框出现问题。不知怎的,它可能与自己不同步。例如,在我更改我的BlockSequenceFields后,只有下拉文本被更改。下面,字段1已更新,但您可以看到它没有反映在当前选定的项目中。

enter image description here

我的IsSynchronizedWithCurrentItem = true应该使当前选定的项目按预期运行,但似乎不起作用。我已经阅读了许多当前项目不匹配的stackoverflow帖子,但他们只是将IsSynchronizedWithCurrentItem设置为true并修复了它们的问题。

有谁可以解释为什么这对我不起作用?

    <ComboBox x:Name="SequenceFieldComboBox" 
              SelectedItem="{Binding BlockSequenceFieldIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
              ItemsSource="{Binding BlockSequenceFields, UpdateSourceTrigger=PropertyChanged}"   
              IsSynchronizedWithCurrentItem="True">

        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <CheckBox
                        IsChecked="{Binding IsCalibrated, Mode=OneWay}"
                        IsEnabled="False">
                    </CheckBox>
                    <TextBlock 
                        Text="{Binding}">
                    </TextBlock>
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

编辑:张伯伦先生的进一步细节

// ViewModelBase implements INotifyPropertyChanged
public class BlockFieldViewModel : ViewModelBase
{
    public BlockSequenceField SequenceField { get; set; }

    public List<BlockSequenceCalibrationItemViewModel> Calibrations => this.SequenceField?.CalibrationList;

    public bool IsCalibrated => this.Calibrations.TrueForAll(x => x.IsCalibrated == null || x.IsCalibrated == true);

    public double AmplitudeThreshold => this.Calibrations.Max(x => x.Amplitude);

    public int FieldNumber { get; set; }

    public override string ToString()
    {
        string ret = string.Format(CultureInfo.CurrentCulture, "Field {0} ", this.FieldNumber);

        if (Math.Abs(this.AmplitudeThreshold) > .00001)
        {
            ret = string.Concat(ret, string.Format(CultureInfo.CurrentCulture, "({0} mA)", this.AmplitudeThreshold));
        }

        return ret;
    }
}

这是更大的viewmodel,称之为MainViewModel.cs。以下是班级中的相关字段

    private ObservableCollection<BlockFieldViewModel> blockSequenceFields;

    public ObservableCollection<BlockFieldViewModel> BlockSequenceFields
    {
        get => this.blockSequenceFields;
        set
        {
            this.blockSequenceFields = value;
            this.OnPropertyChanged("BlockSequenceFields");
        }
    }

    private void RefreshFieldList()
    {
        // In order for the combo box text to update, we need to reload the items
        var savedIndex = this.BlockSequenceFieldIndex;  // to restore to current field.
        var fieldList = this.CalibrationViewModel.FieldViewModels;
        this.BlockSequenceFields = new ObservableCollection<BlockFieldViewModel>(fieldList); 
        this.BlockSequenceFieldIndex = savedIndex;
    }

1 个答案:

答案 0 :(得分:1)

导致问题的原因是更新FieldNumber时BlockFieldViewModel不会引发INPC。您需要至少为该属性提高它。

//Assuming the base class looks like
public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}


public class BlockFieldViewModel : ViewModelBase
{
   //...

    public int FieldNumber 
    { 
        get
        {
            return _fieldNumber;
        }
        set
        {
            if(_fieldNumber.Equals(value))
                return;

            OnPropertyChanged();
        }
    }
    //...
}

我不确定这是否能解决您的问题,因为您使用.ToString()来显示名称。如果您发现上面没有修复它,则通过将空字符串传递给OnPropertyChanged方法来触发为整个对象更改的属性

public int FieldNumber 
{ 
    get
    {
        return _fieldNumber;
    }
    set
    {
        if(_fieldNumber.Equals(value))
            return;

        //Refresh all properties due to the .ToString() not updating.
        OnPropertyChanged("");
    }
}

此外,如果可以添加或删除List<BlockSequenceCalibrationItemViewModel> Calibrations,或者可以更改.Amplitude,则需要从中触发更新名称。