属性 returns 与设置的值不同

Property returns different value than what was set

我正在开发 Visual Studio 扩展,我当前的目标是在“工具”菜单中设置一个菜单项。单击此菜单项时,将打开一个 WinForms window,其中包含一个 ListView、3 个文本框和一个按钮。这个想法是,当您单击 ListView 中的其中一行时,该行的数据将填充到文本框中,以便您可以更新它。如果单击该按钮,将添加一个新行并清除文本框。但是,我在获取所选行的索引时遇到问题。

private int _index;

private void newSourceBtn_Click(object sender, EventArgs e)
{
    // Add new row to the ListView
    ListViewItem row = new ListViewItem();
    row.SubItems.Add("new");
    row.SubItems.Add(String.Empty);
    row.SubItems.Add(String.Empty);

    remoteSourceListView.Items.Add(row);
    int index = remoteSourceListView.Items.Count - 1;
    remoteSourceListView.Items[index].Selected = true;

    newSourceAdded = true;
    sourceNameTextBox.Clear();
    sourceUrlTextBox.Clear();
}

public void SourceName_TextChanged(object sender, EventArgs e)
{
    remoteSourceListView.Items[IndexSelected].SubItems[1].Text = sourceNameTextBox.Text;
}

public void SourceURL_TextChanged(object sender, EventArgs e)
{
    string url = sourceUrlTextBox.Text;
    if ((url.StartsWith("http")) || (url.StartsWith("https")) || (url.StartsWith("git")))
    {
        sourceBranchTextBox.Enabled = true;
    }

    remoteSourceListView.Items[IndexSelected].SubItems[2].Text = url;
}

public void SourceBranch_TextChanged(object sender, EventArgs e)
{

}

public void SourcesListView_SelectedIndexChanged(object sender, EventArgs e)
{
    ListView.SelectedListViewItemCollection selectedRows = remoteSourceListView.SelectedItems;

    foreach (ListViewItem row in selectedRows)
    {
        sourceNameTextBox.Text = row.SubItems[1].Text;
        sourceUrlTextBox.Text = row.SubItems[2].Text;

        IndexSelected = row.Index;

        if (row.SubItems[3].Text != "")
        {
            sourceBranchTextBox.Enabled = true;
            sourceBranchTextBox.Text = row.SubItems[3].Text;
        }
    }
}

public int IndexSelected
{
    get { return _index; }
    set { _index = value; }
}

此代码显示将新行添加到 ListView 的按钮单击事件、更新 ListView 中行的每个文本框的文本更改事件(排序)以及 ListView 的选定索引更改事件这是我获取刚刚选择的行的索引的地方。在调试时,我注意到当我点击一行时,我在选定的索引更改事件中获得了正确的索引;但是,当我从任一文本更改事件中调用 IndexSelected 时,它总是给我一个不同的索引。

有什么建议吗?

从发布的代码中我找不到任何解释所记录行为的原因。
一个可能的原因可能是 insertion/deletion of new/existing ListViewItem 位于保存的 RowIndex 之前的位置。

然而,另一种方法是可行的。您可以尝试将全局 属性 设置为所选的 ListViewItem 并在需要设置其子项时重用该实例,而不是保留 RowIndex 。

如果 ListViewItems 的数量发生变化并且某些项目在保存的 RowIndex 之前 inserted/removed,则可以通过这种方式避免问题。但是,应提供防止空值的保护措施。

private ListViewItem CurrentItemSelected {get;set;}
......

public void SourcesListView_SelectedIndexChanged(object sender, EventArgs e)
{
    ListView.SelectedListViewItemCollection selectedRows = remoteSourceListView.SelectedItems;

    foreach (ListViewItem row in selectedRows)
    {
        sourceNameTextBox.Text = row.SubItems[1].Text;
        sourceUrlTextBox.Text = row.SubItems[2].Text;

        CurrentItemSelected = row;

        if (row.SubItems[3].Text != "")
        {
            sourceBranchTextBox.Enabled = true;
            sourceBranchTextBox.Text = row.SubItems[3].Text;
        }
    }
}

public void SourceName_TextChanged(object sender, EventArgs e)
{
    if(CurrentItemSelected != null)
        CurrentItemSelected.SubItems[1].Text = sourceNameTextBox.Text;
}

但是,我对你的代码有点困惑。您是否将 属性 MultiSelect 设置为 true?因为如果它设置为 false 那么您的代码就不需要循环。

public void SourcesListView_SelectedIndexChanged(object sender, EventArgs e)
{
    if(remoteSourceListView.SelectedItems.Count > 0)
    {
        // With MultiSelect = false; there is only one selected item.
        CurrentItemSelected = remoteSourceListView.SelectedItems[0];
        sourceNameTextBox.Text = CurrentItemSelected.SubItems[1].Text;
        sourceUrlTextBox.Text = CurrentItemSelected.SubItems[2].Text;
        if (CurrentItemSelected.SubItems[3].Text != "")
        {
            sourceBranchTextBox.Enabled = true;
            sourceBranchTextBox.Text = CurrentItemSelected.SubItems[3].Text;
        }
    }
}