【问题标题】:C# WPF ListView not deleting items properlyC# WPF ListView 没有正确删除项目
【发布时间】:2018-10-25 15:19:54
【问题描述】:

我有一个ListView,看起来像这样;

<Window x:Class="WPF_Viewer.URLLinks"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WPF_Viewer"
    mc:Ignorable="d"
    Title="URLLinks" Height="461.215" Width="606.542" WindowStartupLocation="CenterScreen">
<Grid>
    <ListView x:Name="proxyListView" Loaded="proxyListView_Loaded">
        <ListView.ContextMenu>
            <ContextMenu Name="contextMenu1">
                <MenuItem Name="item1" Header="Delete" Click="item1_Click"/>
            </ContextMenu>
        </ListView.ContextMenu>
    </ListView>
</Grid>
</Window>

我正在尝试添加 ContextMenu 以删除 SelectedItem 这是后面的代码;

public partial class URLLinks : Window
{
    public URLLinks()
    {
        InitializeComponent();
    }

    private void proxyListView_Loaded(object sender, RoutedEventArgs e)
    {
        proxyListView.ItemsSource = GlobalVars.URLLinks;
    }

    private void item1_Click(object sender, RoutedEventArgs e)
    {
        GlobalVars.URLLinks.RemoveAt(proxyListView.SelectedIndex);
        ICollectionView view = CollectionViewSource.GetDefaultView(proxyListView.ItemsSource);
        //view.Refresh();
    }
}

有什么想法吗?

编辑:这是变量及其设置方式

public static async void GetLink(string url)
    {
        try
        {
            string sURL = url;
            Uri uri = new Uri(sURL);
            string host = uri.Host;
            using (HttpClient clientduplicate = new HttpClient())
            {
                clientduplicate.DefaultRequestHeaders.Add("User-Agent",
                    "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident / 6.0)");
                using (HttpResponseMessage responseduplicate = await clientduplicate.GetAsync(sURL))
                {
                    using (HttpContent contentduplicate = responseduplicate.Content)
                    {
                        try
                        {
                            string resultduplicate = await contentduplicate.ReadAsStringAsync();
                            var websiteduplicate = new HtmlAgilityPack.HtmlDocument();
                            websiteduplicate.LoadHtml(resultduplicate);
                            List<string> ListItems = new List<string>();
                            Settings.Default.Reload();
                            int maxLinks = Convert.ToInt32(Math.Round(Convert.ToDouble(Settings.Default["subLinksValue"]) * 10));

                            foreach (HtmlNode links in websiteduplicate.DocumentNode.SelectNodes("//a[@href]"))
                            {
                                HtmlAttribute att = links.Attributes["href"];
                                foreach (var link in att.Value.Split(' '))
                                {
                                    if (ListItems.Count >= maxLinks)
                                    {
                                        GlobalVars.URLLinks = ListItems;
                                        //File.WriteAllLines(AppDomain.CurrentDomain.BaseDirectory + @"\links.txt", ListItems.ToArray());
                                        return;
                                    }
                                    if (link.StartsWith("http") && link.Contains(host) && CheckURLValid(link))
                                    {
                                        ListItems.Add(link);
                                    }
                                }
                            }
                            GlobalVars.URLLinks = ListItems;
                            //File.WriteAllLines(AppDomain.CurrentDomain.BaseDirectory + @"\links.txt", ListItems.ToArray());
                            //return ListItems;
                        }
                        catch (Exception ex1)
                        {
                            Console.WriteLine("Error getting links");
                            //return null;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            System.Windows.MessageBox.Show("Error, url not formatted correctly. Try coping your url from your browser");
        }
    }

【问题讨论】:

  • URLLinks 使用 ObservableCollection。不需要view.Refresh();
  • 改成public static IList&lt;string&gt; URLLinks = new ObservableCollection&lt;string&gt;();
  • 它不会更新。顺便说一句,我在 Window 7 上。附:你的意思是添加 INotifyCollectionChanged?
  • 不,只是 ObservableCollection 而不是 List。
  • 如果您重新分配它,它必须触发属性更改通知,例如StaticPropertyChanged event.

标签: c# wpf listview delete-row selecteditem


【解决方案1】:

如果GlobalVars.URLLinks 返回ObservableCollection&lt;T&gt; 或任何其他实现INotifyCollectionChanged 接口的自定义类型,这将起作用:

private void item1_Click(object sender, RoutedEventArgs e)
{
    var ic = proxyListView.ItemsSource as IList<string>;
    ic.RemoveAt(proxyListView.SelectedIndex);
}

但是,如果源集合在删除项目时未引发更改通知(List&lt;T&gt; 不会),则您必须在删除项目后重新设置 ItemsSource 属性以刷新 @ 987654327@:

private void item1_Click(object sender, RoutedEventArgs e)
{
    GlobalVars.URLLinks.RemoveAt(proxyListView.SelectedIndex);
    proxyListView.ItemsSource = GlobalVars.URLLinks;
}

【讨论】:

  • 我已经用变量 public static List URLLinks = new List(); 编辑了答案
  • @JohnP。所以需要把源集合的类型改成ObservableCollection&lt;T&gt;或者重新设置ItemsSource。查看我的答案并进行编辑。
  • 这就是为什么我说它不能正常工作。您建议的第二种解决方案是我正在使用的解决方案。它并不总是删除选定的项目。
  • @mm8 在删除第一个解决方案后,这两种解决方案都出现Index out of range 异常,仅供参考。
  • @James 当然,因为在您删除所选项目后选择就消失了。然后 SelectedIndex 将变为 -1。当然,您必须检查索引是否有效。但这超出了问题的范围。
【解决方案2】:

即使您不打算走完整的 MVVM 路线,至少也要使用 ObservableCollection 项目并将您的 ListView 的 ItemSource 分配给它。这将在删除或添加项目时自动更新控件。

尝试在 UI 上执行业务逻辑操作。控制很快就会沦为一团意大利面。

【讨论】:

    【解决方案3】:

    为了让它发挥作用,我唯一要做的就是将你的收藏从 List&lt;string&gt; 更改为 ObservableCollection&lt;string&gt;

    执行此操作后,您无需重置列表视图中的项目。

    static ObservableCollection<string> items = new ObservableCollection<string>() { "Item 1", "Item 2" };
    
    private void proxyListView_Loaded(object sender, RoutedEventArgs e)
    {
        proxyListView.ItemsSource = items;
    }
    
    private void item1_Click(object sender, RoutedEventArgs e)
    {
        items.RemoveAt(proxyListView.SelectedIndex);
    } 
    

    【讨论】:

    • 我的物品清单在另一个班级这一事实是否会影响这一点。因为当我在同一个表单中移动我的列表时它可以工作,当它在 Glabal 范围内时,它不会?
    • @JohnP。消极的。我将items 属性移到另一个类,它工作得很好。
    • @JohnP。您对我的解决方案有何影响?
    • 应该是更新GlobalVars.URLLinks的函数。更新主线程
    猜你喜欢
    • 2019-09-10
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多