3

我的ListView应用程序中有一个当前填充了 2 个项目。

<ListView Name="lstViewFolderSettings" Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="0" SelectionMode="Single" SelectionChanged="lstViewFolderSettings_SelectionChanged">
    <ListView.View>
        <GridView>
            <GridViewColumn Width="100" Header="Type" DisplayMemberBinding="{Binding Name}"  />
            <GridViewColumn Width="250" Header="Folder" DisplayMemberBinding="{Binding FolderPath}" />
            <GridViewColumn Width="350" Header="XPath" DisplayMemberBinding="{Binding XPath}" />
        </GridView>
    </ListView.View>
</ListView>

然后我将我ItemsSource的设置如下

lstViewFolderSettings.ItemsSource = fileSeperationSettings.FileSettings;

SelectionChanged事件我得到填充一些控件的选定项目。然后我点击保存然后更新我的收藏并ItemsSource再次重置

lstViewFolderSettings.ItemsSource = null;
lstViewFolderSettings.ItemsSource = fileSeperationSettings.FileSettings;

我必须先设置为 null 否则ListView视图中不会更新

这一切似乎工作正常,直到我在同一个项目上更改我的选择两次。


选择项目 1 -> 更改 -> 更新
选择项目 2
选择项目 1
选择项目 2 -> BANG!

砰!我指的是

ArgumentException 未处理
已添加具有相同键的项目。

堆栈跟踪:

at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2..ctor(IDictionary`2 dictionary, IEqualityComparer`1 comparer)
at System.Windows.Controls.Primitives.Selector.InternalSelectedItemsStorage..ctor(InternalSelectedItemsStorage collection, IEqualityComparer`1 equalityComparer)
at System.Windows.Controls.Primitives.Selector.SelectionChanger.ApplyCanSelectMultiple()
at System.Windows.Controls.Primitives.Selector.SelectionChanger.End()
at System.Windows.Controls.Primitives.Selector.SetSelectedHelper(Object item, FrameworkElement UI, Boolean selected)
at System.Windows.Controls.Primitives.Selector.NotifyIsSelectedChanged(FrameworkElement container, Boolean selected, RoutedEventArgs e)
at System.Windows.Controls.Primitives.Selector.OnSelected(Object sender, RoutedEventArgs e)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
at System.Windows.Controls.ListBoxItem.OnSelected(RoutedEventArgs e)

--- 更新 --- SelectionChanged 事件处理程序代码。

private void lstViewFolderSettings_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    m_SelectedSetting = lstViewFolderSettings.SelectedItem as FileSetting;
    txtFolder.Text = m_SelectedSetting.FolderPath;
    txtType.Text = m_SelectedSetting.Name;
    txtXPath.Text = m_SelectedSetting.XPath;

     e.Handled = true;
}

- 更新 - -

所以我现在有了这个

ObservableCollection<FileSetting> _fileSettings;
public ObservableCollection<FileSetting> FileSettings
{
    get 
    {
        if (_fileSettings == null)
  {
            FileSeperationSettings fileSeperationSettings = m_config.GetSection("fileSeperationSettings") as FileSeperationSettings;

            _fileSettings = new ObservableCollection<FileSetting>(fileSeperationSettings.FileSettings.Cast<FileSetting>());
        }

        return _fileSettings;
    }
}

我从这个集合中添加和删除

FileSettings.Add(fsSetting);
FileSettings.Remove(fsSetting);

我得到选定的项目

m_SelectedSetting = lstViewFolderSettings.SelectedItem as FileSetting;

txtFolder.Text = m_SelectedSetting.FolderPath;
txtType.Text = m_SelectedSetting.Name;
txtXPath.Text = m_SelectedSetting.XPath;

我更新项目

FileSetting fs = FileSettings.First(x => x.Name == m_SelectedSetting.Name);
fs.Name = txtType.Text;
fs.FolderPath = txtFolder.Text;
fs.XPath = txtXPath.Text;

在我进行更新然后第二次更改所选项目后发生错误...

4

2 回答 2

1

我通过阅读以下内容解决了这个问题can't clear WPF ListBox.SelectedItems collection我意识到它不会删除我的 selectedItem 的原因是因为它在集合中不存在(HashCode 已更改),或者类似的东西。 ..

所以我将 selectionChanged 事件更改为以下

FileSetting selectedItem;
private void lstViewFolderSettings_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    selectedItem = lstViewFolderSettings.SelectedItem as FileSetting;
    txtFolder.Text = selectedItem.FolderPath;
    txtType.Text = selectedItem.Name;
    txtXPath.Text = selectedItem.XPath;

    lstViewFolderSettings.UnselectAll();
}

所以我现在自己跟踪所选项目。这意味着我可以随意设置和重新设置 ItemsSource。

于 2013-09-03T15:19:16.617 回答
0

我会远离代码隐藏并更多地使用数据绑定。

您的收藏应该是 UI 的属性DataContext

public class MyViewModelOrCodeBehindClass
{
    public FileSetting SelectedItem { get; set; }

    public ObservableCollection<FileSetting> FileSettings 
    {
        get; 
        private set; 
    }

    public MyViewModel()
    {
        FileSettings = new ObservableCollection<FileSetting>();
        // If you're using codebehind rather than having something 
        // else set this class as the datacontext:
        DataContext = this;
    }
}

在您看来:

<ListView ItemsSource="{Binding FileSettings}" SelectedItem="{Binding SelectedItem}" />
<TextBlock Text="{Binding SelectedItem.Folder}" />
<TextBlock Text="{Binding SelectedItem.Name}" />
<TextBlock Text="{Binding SelectedItem.XPath}" />

在您的代码隐藏/视图模型中,您只需添加/删除项目,数据绑定将完成其余工作。更好的是,如果列表中的每个项目都实现了INotifyPropertyChanged,那么对这些项目的编辑也将在 UI 中自动更新。你根本不需要处理SelectionChanged

于 2013-09-03T13:25:38.527 回答