【问题标题】:How can I filter different things according to a class attribute?如何根据类属性过滤不同的东西?
【发布时间】:2010-01-03 23:33:57
【问题描述】:

这是我将要做的事情的要点。

这是我的英雄职业:

namespace TomeOfNewerth_WPF_
{
    public enum HeroType
    {
        Agility,
        Strength,
        Intelligence
    }

    public enum AttackType
    {
        Melee,
        Ranged,
    }

    class Hero
    {
        public string Faction;
        public string Name;
        public HeroType HeroType;
        public string Backstory;
        public double MinimumDamage;
        public double MaximumDamage;
        public double Armor;
        public double MoveSpeed;
        public AttackType AttackType;
        public double AttackRange;
        public double AttackRate;
        public int Strength;
        public int Agility;
        public int Intelligence;
        public string DOTAVersion;

        //Default constructer required for XML serialization.
        public Hero()
        { }

        /// <summary>
        /// This method returns a hero full of the necessary information.
        /// </summary>
        /// <param name="Name">Name of the hero.</param>
        /// <returns>Returns an instace of the Hero class chock full of information.</returns>
        public Hero GetHero(string Name)
        {
            Hero NewHero = new Hero();

            NewHero.Faction = "Legion";
            NewHero.Name = "Andromeda";
            //Yada yada yada. I have to complete this, so disregard it.

            return NewHero;
        }
    }
}

该类的每个属性都是一个 XML 元素。我已经手动将所有信息列表到一个 XML 文件中,因此我可以将其反序列化到 Hero 类中并将实例转发到需要它的任何地方。

有一个用例我无法理解。

我有两个按钮,ViewGood 和 ViewEvil。

Hero 类有一个名为 Faction 的属性,我必须过滤掉哪些英雄有善,哪些英雄有恶。

我想做的事:

  1. 我有一个循环的方法 通过 XML 中的每个节点和 返回一个包含所有的列表 与请求的 HEROTYPE 匹配的英雄名称。

  2. 使用该列表,我可以 做一个foreach,因为所有的英雄 在表单上有一个图像控件 x:Name 设置为 Hero 名字,我可以做一个 .Visibilty = Visibility.False 为所有,并设置它 忠实于每一个英雄的名字 列表。有效隐藏每个图像控件 不在列表中。

我对你们的问题是,我是在做完全智障的事情吗?我真的很想花更多的时间让这个程序有漂亮干净的代码,因为我想学习比什么都重要。

谢谢,所以。 :)

【问题讨论】:

  • 我想知道为什么有些人不赞成我的问题。字数太多,看不懂?
  • 我也不知道——这是一个不无道理的问题

标签: c# wpf xml


【解决方案1】:

我不明白。您想要一个按属性过滤的列表吗?

像这样?

List<Hero> heroes = GetYourHeroes();
var goodGuys = heroes.Where(hero => hero.Faction == "Jedi");

编辑以回答评论:

你的第二行是否相当于做一个 foreach 并询问 hero.Faction == "Jedi"

或多或少,是的。在大多数情况下,它的行为是相同的,但底层 LINQ 的行为却截然不同。如果您喜欢这种语法,我建议您阅读或查看本网站上的 LINQ 问题。

可能会咬你的主要区别是默认情况下这是惰性的。

Where(hero =&gt; hero.Faction == "Jedi") 返回一个 IEnumerable&lt;Hero&gt; 并且实际上不会执行您想要的操作,除非您手动或通过将结果转换为列表来真正迭代枚举器:

Where(hero =&gt; hero.Faction == "Jedi").ToList() 可能会做你最初期望的事情:这会给你一个已经代表过滤结果的列表。

不过,请记住懒惰,它在以后非常有用,例如当您构造和嵌套多个这样的“查询”时。

【讨论】:

  • 嗨 Pap,Ben 的回答使用了一种叫做 LINQ 的东西,它本质上允许您对对象集合执行查询。它非常适合您正在做的事情。
  • 你好,本杰明。你的第二行是否相当于做一个 foreach 并询问 hero.Faction = "Jedi" 吗?如果是这样,那就太性感了。
  • 结果是一样的,但它以更优化的方式实现,因此性能会更好。或者至少我认为是!
  • Paul:我很确定它不会表现得更好。在幕后,.Where 只是使用 IEnumerator 进行枚举,与 foreach 完全相同。
  • 不过确实很性感。
【解决方案2】:

您是否希望对 XML 进行一些查询?你想要 XPath:http://www.w3schools.com/XPath/default.asp & http://www.codeproject.com/KB/cpp/myXPath.aspx

【讨论】:

    【解决方案3】:

    在 WPF 中执行此操作的一种简单方法是使用 CollectionView 而不是原始列表作为您的 ItemsSource。然后您可以对此设置过滤器,您的列表控件将仅显示通过过滤器的项目。

    但是,听起来您将图像控件直接添加到面板(画布?)而不是使用列表控件。在这种情况下,迭代图像控件并设置它们的可见性是一种方法。另一种方法是创建一个视图模型类,它使用诸如可见性之类的显示属性来扩充 Hero 类,并在用户选择不同的视图按钮时更新该可见性。然后,您的 Image 控件可以将其 Visibility 数据绑定到视图模型 Visibility。在视图模型中执行此操作而不是直接操作 Image 控件的优点是可测试性:对于像这样的简单案例来说没什么大不了的,但对于复杂的应用程序却越来越重要。

    顺便说一句,如果您目前正在手动添加图像,但您的设计还没有确定,我强烈建议您研究使用 ItemsControl 来处理集合的显示。 (请记住,ListBox 不仅仅是一个垂直堆栈:您可以使用它以您选择的任何布局显示内容。)这将删除大量繁琐的迭代代码!

    【讨论】:

      【解决方案4】:

      如果您不打算使用 itowlson 的使用 CollectionView 的建议(有利也有弊),另一种处理方法是向您的类添加 IsVisible 属性,然后实现 INotifyPropertyChanged。那么在 WPF 中支持显示/隐藏就非常简单了:

      <DataTemplate DataType="{x:Type local:Hero}">
         <StackPanel Orientation="Horizontal" IsVisible="{Binding IsVisible}">
            <TextBlock Text="{Binding Faction}"/>
            <TextBlock Text="{Binding Name}"/>
               ... etc.
         </StackPanel>
      </DataTemplate>
      
      <ListBox ItemsSource="{Binding MyDataSource.HeroesCollection}"/>
      

      (您可能会使用Grid 而不是StackPanel;这只是为了显示Hero 对象的DataTemplate 可能是什么样子。)

      重要的是IsVisible 属性的类型为Visibility,而不是布尔值,除非您想实现一个值转换器来将true 转换为Visibility.VisiblefalseVisibility.Collapsed,例如@ 987654321@.

      一旦你这样做,做这样的事情:

      foreach (Hero h in HeroesCollection)
      {
         h.IsVisible = h.Faction == selectedFaction 
            ? Visiblity.Visible 
            : Visibility.Collapsed;
      }
      

      会像魔术一样工作。 (如果你已经实现了INotifyPropertyChanged。如果你没有实现,什么都不会发生,因为UI 不会知道Visibility 属性发生了变化。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-08
        • 2010-10-06
        • 2018-10-12
        • 2022-01-23
        • 1970-01-01
        • 2012-08-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多