C# 组合框已选择索引绑定-1或0未选择第一项

C# 组合框已选择索引绑定-1或0未选择第一项,c#,wpf,xaml,combobox,C#,Wpf,Xaml,Combobox,我有一个组合框,当SelectedItem被更改时,它会写入配置文件。 我想使用SelectedIndex=-1作为备用,以防SelectedItem丢失 我不希望SelectedIndex在程序启动时触发并写入配置文件,所以我将事件处理程序放在C窗口中,而不是XAML 问题是Video_SelectedIndex=-1没有选择任何内容,它会将SelectedItem留空 主窗口 XAML 选择项目/索引 值-1表示未选择任何元素。必须将其设置为0才能获取第一项 如下所述: 垂涎三尺 为什么不在

我有一个组合框,当SelectedItem被更改时,它会写入配置文件。 我想使用SelectedIndex=-1作为备用,以防SelectedItem丢失

我不希望SelectedIndex在程序启动时触发并写入配置文件,所以我将事件处理程序放在C窗口中,而不是XAML

问题是Video_SelectedIndex=-1没有选择任何内容,它会将SelectedItem留空

主窗口 XAML 选择项目/索引
值-1表示未选择任何元素。必须将其设置为0才能获取第一项

如下所述:

垂涎三尺

为什么不在setter中写入config

private int _Video_SelectedIndex { get; set; }
public int Video_SelectedIndex
{
    get { return _Video_SelectedIndex; }
    set
    {
        if (_Video_SelectedIndex == value)
        {
            return;
        }

        _Video_SelectedIndex = value;
        OnPropertyChanged("Video_SelectedIndex");

       //write to config
    }
}
这样您就不会得到SelectionChange从nothing-1到0,因为_Video_SelectedIndex将被初始化为0,如果_Video_SelectedIndex==值从0变为0,则将阻止触发

作为补充说明,为什么您将_Video_SelectedIndex声明为属性而不是字段

那么,为什么会这样:

private int _Video_SelectedIndex { get; set; }
而不是

private int _Video_SelectedIndex;
编辑:

我不能重现你的问题,也许我做的这个小测试项目会帮助你

如果没有,请进行必要的更改以显示您的问题

注意,我已经测试了SelectedIndex和SelectedItem

MainWindow.xaml

MyViewModel.cs

只有当用户手动更改combox值时,才会命中//写入配置部分,而不会在启动时自动命中

要在配置返回null或-1时使用默认值,可以更改以下代码:

//read config
_selectedItem = _config.SelectedItem;
_selectedIndex = _config.SelectedIndex;
为此:

//read config
_selectedItem = _config.SelectedItem ?? Items.First();
_selectedIndex = _config.SelectedIndex == -1 ? 0 : _config.SelectedIndex;
或者,为了准确检查存储在_config中的值是否仍然有效,您可以使用

_selectedItem = Items.Contains(_config.SelectedItem) ? _config.SelectedItem : Items.First();
_selectedIndex = _config.SelectedIndex >= Items.Count() || _config.SelectedIndex < 0 ? 0 : _config.SelectedIndex;

问题是Video_SelectedIndex=-1没有选择任何内容,它会将SelectedItem留空。有打字错误吗?cboPlugin\u Video.SelectedIndex+=VM.pluginView.Video\u SelectedIndex;-它不应该只是=而不是+=?@RandRandom问题看起来是+=和-1而不是0,但是在将其更改为=,它现在在启动时启动。@RandRandRandom我认为我无法将其正确绑定到ViewModel。我想我必须将主窗口传递给它,并使用MainWindow.cboPlugin\u Video.SelectedIndex=0您可以在ContentRendered而不是loaded上注册SelectionChanged事件-这应该发生在所有已评估的绑定之后我尝试在setter中写入配置,但binding SelectedIndex在启动时仍会以任何方式启动。{get;set;}很可能是我所遵循的一个例子中的意外事件。@mattmcanis-看看我的edit@MattMcManis-你的问题解决了吗?
private int _Video_SelectedIndex { get; set; }
public int Video_SelectedIndex
{
    get { return _Video_SelectedIndex; }
    set
    {
        if (_Video_SelectedIndex == value)
        {
            return;
        }

        _Video_SelectedIndex = value;
        OnPropertyChanged("Video_SelectedIndex");

       //write to config
    }
}
private int _Video_SelectedIndex { get; set; }
private int _Video_SelectedIndex;
<Window x:Class="WpfApp10.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp10">
    <Window.DataContext>
        <local:MyViewModel />
    </Window.DataContext>
    <StackPanel Orientation="Vertical">
        <TextBlock Text="ComboBox with SelectedItem" />
        <ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" />

        <TextBlock Text="ComboBox with SelectedIndex" />
        <ComboBox ItemsSource="{Binding Items}" SelectedIndex="{Binding SelectedIndex}" />
    </StackPanel>
</Window>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}
public class MyViewModel : INotifyPropertyChanged
{
    private Config _config;
    private string _selectedItem;
    private int _selectedIndex;
    
    public event PropertyChangedEventHandler? PropertyChanged;

    public IEnumerable<string> Items { get; set; } = Enumerable.Range(0, 10).Select(x => $"Foo {x}");

    public string SelectedItem
    {
        get => _selectedItem;
        set
        {
            if (_selectedItem == value)
                return;
            
            _selectedItem = value;
            OnPropertyChanged();
            
            //write config
            _config.SelectedItem = value;
        }
    }
    public int SelectedIndex
    {
        get => _selectedIndex;
        set
        {
            if (_selectedIndex == value)
                return;
            
            _selectedIndex = value;
            OnPropertyChanged();
            
            //write config
            _config.SelectedIndex = value;
        }
    }

    public MyViewModel()
    {
        _config = new Config();
        
        //read config
        _selectedItem = _config.SelectedItem;
        _selectedIndex = _config.SelectedIndex;
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
public class Config
{
    public string SelectedItem { get; set; }
    public int SelectedIndex { get; set; }

    public Config()
    {
        //fake reading stuff from *.config file
        
        //test it with either of those
        
        //SelectedItem = "Foo 2";
        //SelectedIndex = 2;

        SelectedItem = null;
        SelectedIndex = -1;
    }
}
//read config
_selectedItem = _config.SelectedItem;
_selectedIndex = _config.SelectedIndex;
//read config
_selectedItem = _config.SelectedItem ?? Items.First();
_selectedIndex = _config.SelectedIndex == -1 ? 0 : _config.SelectedIndex;
_selectedItem = Items.Contains(_config.SelectedItem) ? _config.SelectedItem : Items.First();
_selectedIndex = _config.SelectedIndex >= Items.Count() || _config.SelectedIndex < 0 ? 0 : _config.SelectedIndex;